Symbol

133 阅读3分钟

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

Symbol出现的原因

ES5中,对象的属性名都是字符串,容易造成属性名称冲突,于是,在ES6中引入原始数据类型Symbol ,表示独一无二 的值。 即 ES6中的Symbol是一种新的基本数据类型,它是一种唯一且不可变的值,用于创建对象属性的唯一标识符

特性

  • Symbol的值是唯一且不可变的,即使创建多个相同描述符的Symbol,它们也是不同的值。
  • Symbol是原始类型,可以通过typeof运算符来检测它们。
  • Symbol可以作为对象属性的键名,用于避免属性名冲突。
  • Symbol创建的属性可以通过Object.getOwnPropertySymbols()方法获取,而不是Object.keys()方法。
let s = Symbol();
typeof s  // "symbol"

typeof运算符的结果,表明变量s是 Symbol 数据类型,而不是字符串之类的其他类型

使用限制

  • Symbol不能被New操作符调用,因为它不是构造函数。
  • Symbol不能被强制转换为字符串或数字类型,因为它们是原始类型,而不是对象。
  • Symbol不能被迭代,因为它们不是可迭代的数据类型。

因此,我们不能使用for...of或forEach等迭代器循环Symbol。如果我们需要遍历对象的Symbol属性,可以使用Object.getOwnPropertySymbols()方法来获取Symbol属性,并手动遍历它们。

使用-例子

Symbol 的值是通过Symbol 函数生成的

对象属性-在对象字面量中使用 Symbol 作为键

不能使用点语法访问以 Symbol 为键的属性,必须使用方括号来访问属性

let id = Symbol("id");

let obj = {
  [id]: 1
}

console.log(obj[id])

常见的对象检查功能会跳过 Symbol

  • 在 JavaScript 最常见的对象检查功能(例如 for-in 循环)中会跳过 Symbol 属性
  • 在 Object.keys(obj) 和 Object.getOwnPropertyNames(obj) 中也将忽略作为属性键的 Symbol
  • 使用 JSON.stringify() 时,将忽略对象的 Symbol 属性

Symbol 值作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回

优缺点:

  • 优点:Symbol可以避免属性名冲突,使代码更加安全和可读。
  • 缺点:使用Symbol可能会使代码变得更加难懂和复杂,因为它们是不可见的,且不能被序列化和传输。

Symbol.for()

当希望重新使用同一个 Symbol 值,Symbol.for()方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局

Symbol.for()Symbol()这两种写法,都会生成新的 Symbol。

它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值

Symbol.keyFor()

返回一个已登记的 Symbol 类型值的key