ES6 新增数据结构之 Symbol
Symbol
ES5 中的对象属性名都是字符串,这容易造成属性名的冲突。比如,当你想要为一个已有的对象添加一个新属性,而新属性的名字很有可能与现在已有的属性冲突。
为了解决这一问题,ES6 引入了一种新的原始数据类型Symbol,它表示独一无二的值。
1. Symbol值 通过 Symbol()生成。
创建一个 Symbol的实例 :
let s = Symbol()
typeof s // symbol
2. Symbol ( ) 也可以接受一个字符串作为参数,仅表示对生成的symbol值的描述,目的是让人更容易区分。
let s = Symbol('first');
let ss = Symbol('last');
s // Symbol(first)
ss // Symbol(last)
3. Symbol ( ) 的参数只是对当前 Symbol值的描述,相同参数的 Symbol值 是不相等的。
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
let s = Symbol('first');
let ss = Symbol('first');
s === ss // false
4. Symbol ( ) 前不能使用 new ,否则会报错。 记住,新生成的 Symbol值 是一个原始数据类型值,不是对象。
5. Symbol 值不能与其他类型的值进行运算。
6. Symbol 值可以转换为字符串、布尔值。
let s = Symbol('first');
// 可以转换为字符串
s.toString() // 'Symbol('first')'
String(s) // 'Symbol('first')'
// 可以转换为布尔值
Boolean(s) // true
!s // false
if (s) { console.warn( 'true') }
7. 每一个Symbol值都是独一无二,不相等的。 正由于这种特性 Symbol数据类型的主要用途是作为对象属性名。
let mySymbol = Symbol();
var a = {};
a[mySymbol] = 'Hello!';
console.log(a[mySymbol]); // Hello!
var a = {
[mySymbol] : 'World!'
}
console.log(a[mySymbol]); // World!
var a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello World!'})
console.log(a[mySymbol]); // Hello World!
8. Symbol 值作为对象属性名不能使用 点运算符。
let mySymbol = Symbol();
var a = {};
a.mySymbol = 'Hello!';
console.log ( a[mySymbol] ); // undefined
console.log ( a['mySymbol'] ) // Hello!
console.log( a.mySymbol); // Hello!
我们平时调用一个对象属性或方法,是点运算符后接属性名,即 obj.property。也就是说,上面代码其实是将 ‘mySymbol’ 这个字符串作为属性名存 入了 a 对象。
即: a { 'mySymbol' : 'Hello!' }
所以即使是在对象内部,我们定义Symbol值的属性名时,也要写在方括号内。
即正确写法应是:a{ [mySymbol] : 'Hello!' }
9. 重难点:
Symbol 作为属性名,该属性不会出现在for...in
、for...of
循环中,也不会被Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
返回。但是,它也不是私有属性,有一个Object.getOwnPropertySymbols
(),可以获取指定对象的所有 Symbol 属性名。Reflect.ownKeys
() 可以返回所有类型的键名,包括常规键名和 Symbol 键名。
10.Symbol.for(), Symbol.keyFor()
Symbol.for() 接受一个字符串作为参数,然后先搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,没有就新建并返回一个以该字符串为名称的Symbol值。注意,symbol() 返回的值不会在全局环境中登记,一旦创建,就是独一无二的值。
var s = Symbol('123')
var s1 = Symbol.for('123');
var s2 = Symbol.for('123');
s === s1 // false
s1 === s2 // true
Symbol.keyFor()返回一个已登记的 Symbol 类型值的 key。