Symbol(符号)是 ECMAScript 6 新增的数据类型。符号是原始值,且符号实例是唯一、不可变的。
符号的用途是确保对象属性使用唯一标识符,不会发生属性冲突的危险
1、符号的基本用法
符号需要使用 Symbol()函数初始化。因为符号本身是原始类型,所以 typeof 操作符对符号返回 symbol。
let sym = Symbol();console.log(typeof sym); // symbol
2. 使用全局符号注册表
如果运行时的不同部分需要共享和重用符号实例,那么可以用一个字符串作为键,在全局符号注册
表中创建并重用符号。
为此,需要使用 Symbol.for()方法:
let fooGlobalSymbol = Symbol.for('foo');console.log(typeof fooGlobalSymbol); // symbol
Symbol.for()对每个字符串键都执行幂等操作。第一次使用某个字符串调用时,它会检查全局运 行时注册表,发现不存在对应的符号,于是就会生成一个新符号实例并添加到注册表中。后续使用相同 字符串的调用同样会检查注册表,发现存在与该字符串对应的符号,然后就会返回该符号实例。
// 使用Symbol.for前let fooGlobalSymbol = Symbol('foo');let otherFooGlobalSymbol = Symbol('foo');console.log(fooGlobalSymbol === otherFooGlobalSymbol); // false// 使用Symbol.for后let fooGlobalSymbol = Symbol.for('foo'); // 创建新符号let otherFooGlobalSymbol = Symbol.for('foo'); // 重用已有符号console.log(fooGlobalSymbol === otherFooGlobalSymbol); // true// 注意:即使采用相同的符号描述,在全局注册表中定义的符号跟使用 Symbol()定义的符号也并不等同:let localSymbol = Symbol('foo');let globalSymbol = Symbol.for('foo');console.log(localSymbol === globalSymbol); // false
还可以使用 Symbol.keyFor()来查询全局注册表,这个方法接收符号,返回该全局符号对应的字
符串键。如果查询的不是全局符号,则返回 undefined。
// 创建全局符号let s = Symbol.for('foo');console.log(Symbol.keyFor(s)); // foo// 创建普通符号let s2 = Symbol('bar');console.log(Symbol.keyFor(s2)); // undefined如果传给 Symbol.keyFor()的不是符号,则该方法抛出 TypeError:Symbol.keyFor(123); // TypeError: 123 is not a symbol
注意 在提到 ECMAScript 规范时,经常会引用符号在规范中的名称,前缀为@@。比如,
@@iterator 指的就是 Symbol.iterator
3、 Symbol.hasInstance
Symbol.hasInstance 操作符可以用来确定一个对象 实例的原型链上是否有原型
function Foo() {}let f = new Foo();console.log(Foo[Symbol.hasInstance](f)); // trueclass Bar {}let b = new Bar();console.log(Bar[Symbol.hasInstance](b)); // true
4、 Symbol.isConcatSpreadable
数组对象默认情况下会被打平到已有的数组,false 或假值会导致整个对象被追加到数组末尾。类 数组对象默认情况下会被追加到数组末尾,true 或真值会导致这个类数组对象被打平到数组实例。其 他不是类数组对象的对象在 Symbol.isConcatSpreadable 被设置为 true 的情况下将被忽略
let a = {age: 18,name: 'zhangsan'};a[Symbol.isConcatSpreadable] = true;let b = ['html', 'css'];let d = [1, 2, 3]d[Symbol.isConcatSpreadable] = false;console.log(d.length);let c = b.concat(d);console.log(c);//['html','css',[ 1, 2, 3, [Symbol(Symbol.isConcatSpreadable)]: false ]]
