ES6之Symbol

Symbol (符号)是ES6新引入的一种基本数据类型,也就说 ES6 之后,JavaScript 的基本数据类型从原来的 6 种变为了 7 种:Undefined、Null、Boolean、Number、Sting、Object 和 Symbol。

概念

在 ES6 之前,JS代码中每一个值都是以下几种类型之一:

  1. Undefined
  2. Null
  3. Boolean
  4. Number
  5. String
  6. Object

但是现在 ES6 引入了第 7 种原始类型,那就是 Symbol——一种全新的数据类型。新的 Symbol类型的值每一个都是独一无二的,不与其他的 Symbol值相同。Symbol值被创建后就不可变更,也不能为它设置属性。但 Symbo值可以用作对象的属性名称。

通常使用 Symbol() 来生成 Symbol值。每调用一次 Symbol() 都会返回一个全新的唯一 Symbol值。

1
2
3
let s1 = Symbol();
let s2 = Symbol();
console.log(Object.is(s1, s2)); // false

注意:用于生成 Symbol 类型值的 Symbol() 函数之前不能使用 new 关键字,否则会报错。原因在于生成的值本质上是一个原始类型的值而不是引用类型的。

Symbol() 函数还可以接受一个其他类型的值作为参数,这个参数被称作该 Symbol值的 描述

1
2
3
4
5
6
7
Symbol(); // Symbol()
Symbol(undefined); // Symbol()
Symbol(null); // Symbol(null)
Symbol(true); // Symbol(true)
Symol(0); // Symbol(0)
Symbol('a'); // Symbol(a)
Symobl({ }); // Symbol([object Object])

不过通常传入的都是一个字符串参数,这样做是为了使描述具有语义。Symbol() 也可接受多个参数,但只有第一个参数值才有效:

1
Symbol('a', 0, true, {}); // Symbol(a)

注意:Symbol() 函数的参数只是用于描述该 Symbol值,因此即使传入相同的参数,Symbol() 函数返回的值也是不相同的。这正是 Symbol类型值的本质。

获取 Symbol值

有三种获取 Symbol值的方法:

  1. 使用 Symbol(),每调用一次都返回一个新的 Symbol值。
  1. 调用 Symbol.for(string)。使用这种方式首先会访问全局环境下的 Symbol注册表,检查是否已有 Symbol.for() 使用同名参数创建过 Symbol 值,若存在即返回该值;否则,创建一个新的 Symbol值并将其注册到 Symbol注册表中。这种方式与通过Symbol()定义的独立 Symbol值不同,Symbol注册表中的 Symbol值是共享的。与 Symbol.for() 配套有一个 API 方法是 Symbol.keyFor() ,该方法接受一个 Symbol值做参数,返回 Symbol注册表中该 Symbol值的描述。

  2. 使用标准定义的 Symbo值,例如:Symbol.iterator 。ES标准根据一些特殊用途定义了少许的几个 Symbol值。

使用 Symbol值

  • Symbol值不能与其他类型的值进行运算
  • Symbol值可以转为布尔值
  • Symbol值不能被自动转换为字符串,但我们可以显式地使用 toString() 方法将其转化为字符串类型的值

作为对象属性名的 Symbol 值

  • 以 Symbol值作属性名的对象属性被称作一个以 Symbol为键的属性。
  • 由于 Symbol 值的特殊性,当 Symbol 值作为对象的属性名时,只能使用方括号 [] 语法定义及读写,而不能使用. 语法。
  • 对于 Symbol值属性名,我们可以使用 in 语法和 delete 关键字。
  • Symbol 值作为对象的属性名时,该属性名不会出现在 for..infor...of 循环中,也不会被 Object.keys(obj)Object.getOwnPropertyNames(obj) 返回。
  • 利用新的API Object.getOwnPropertySymbols(obj) 方法可以获取指定对象的所有 Symbol键,调用该方法会返回一个的数组,其成员是当前对象属性中所有用作属性名的 Symbol值。
  • 另一个新的API Reflect.ownKeys() 方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。

参考