你真的了解Symbol吗?

217 阅读4分钟

背景

在ES6问世之前,JavaScript的基本数据类型只有5种,分别是String(字符串)Number(数字)Boolean(布尔)Undefined(未定义)Null(空),但是ES6问世后,我们的基本数据类型又新增了两种,分别是Symbol(ES新增)、BigInt(ES10新增)。那新增加这两种基本数据类型是干嘛的呢?有什么作用呢?今天我们们就来好好讲一讲!!

Symbol

什么是Symbol?

Symbol作为基本数据类型的一种,表示独一无二的值,在ES6发布之前,因为对象的键以字符串的形式存在,所以极易引发键名冲突问题,而Symbol的出现正是解决了这个痛点,所以它的使用方式也很简单。

那怎么用Symbol呢?

Symbol() 函数会返回 symbol 类型的值,该类型具有静态属性和静态方法。它的静态属性会暴露几个内建的成员对象;它的静态方法会暴露全局的 symbol 注册,且类似于内建对象类。

注意:因为是Symbol原始数据类型,不是对象所以他并不支持new语法:"new Symbol()" // TypeError

我们要在调用Symbol()时传入一个字符串当做描述值。Symbol(“描述值”)会返回一个唯一的值

let a = Symbol(“description”)
typeof a

属性名的遍历

Symbol 作为属性名,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols方法,可以获取指定对象的所有 Symbol 属性名。

  • Object.getOwnPropertySymbols():返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。
  • Reflect.ownKeys():返回所有类型的键名。
    let obj = {
      [Symbol('my_key')]: 1,
      enum: 2,
      nonEnum: 3
        };
    Reflect.ownKeys(obj)
    //  ["enum", "nonEnum", Symbol(my_key)]

Symbol的使用相对简单,那它的实际是如何应用的呢?

Symbol的实际应用

作为对象的键名(唯一不冲突)

大家肯定都维护过别人写的项目,或者是别人写的代码。因为项目不是我们自己写的。当我们想要给项目里的对象增加一个属性或者方法时,很容易会引起键名重复或者覆盖的问题。这时 Symbol的唯一特性就能很好的帮我们解决这个问题。它可以作为对象的属性的键,并键名避免冲突。

let a = Symbol("a")
let obj = {}
obj[a] = "zayyo"
console.log(obj[a])
  1. 我们创建了一个Symbol基本数据类型(描述符为a)
  2. 我们通过obj[]把a这个Symbol类型的值作为对象的键进行赋值定义

注意:我们不能使用.来调用对象的Symbol属性,所以必须使用[]来访问Symbol属性。因为点运算符后面默认跟的是字符串

方便全局调用同一个Symbol

当我们想在不同的地方调用一个已近定义过的Symbol即全局调用同一个Symbol,可以通过Symbol.for()方法,参数为创建时传入的描述字符串,该方法可以遍历全局注册表中的的Symbol,当搜索到相同描述,那么会调用这个Symbol,如果没有搜索到,就会创建一个新的Symbol

let s1 = Symbol.for('a');
let s2 = Symbol.for('a');
s1 === s2 // true
  1. 首先我们用Symbol.for创建了描述符为a的Symbol基本数据类型
  2. 使用Symbol.for("a")在全局注册表中寻找描述为aSymbol

注意:因为Symbol(‘’)生成的标识是唯一的,所以就算()里的描述值是相同的他们最终返回的值也不是相同的。但是Symbol.for()不同,当()里的描述值是相同时,他们返回的值也是相同的。

  let S1=Symbol('zayyo')
  let S2=Symbol('zayyo')
  let S3=Symbol.for('zayyo')
  let S4=Symbol.for('zayyo')
  console.log(S1===S2)//false
  console.log(S3===S4)//true

Symbol.keyFor()

假如我们想逆推,用Symbol.for("a")返回的值去获得()里的描述值又该怎么办呢?

我们可以使用Symbol.keyFor()

let b = Symbol.for("a")
Symbol.keyFor(b) // 'a'

写在最后

伙伴们,如果你觉得我写的文章对你有帮助就给zayyo点一个赞👍或者关注➕都是对我最大的支持。当然你也可以加我微信:IsZhangjianhao,邀你进我的前端学习交流群,一起学习前端,成为更优秀的工程师~

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 19 天,点击查看活动详情