说明:本文参考阮一峰的ECMAScript 6 入门
Symbol
ES6新增了一种原始数据类型Symbol,表示独一无二的值,用来防止属性名的冲突。
let s = Symbol()
typeof s //"symbol"
上面的代码,表明s是一个独一无二的值。typeof的结果是symbol,表明s是Symbol数据类型,而不是其他数据类型。
注意:Symbol函数前不能使用new命令,因为它返回的是一个原始数据类型,而不是一个对象。因此也不能添加属性。
Symbol函数也可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
let s1 = Symbol('foo');
let s2 = Symbol('bar');
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
上面代码中,s1和s2是两个 Symbol 值。如果不加参数,它们在控制台的输出都是Symbol(),不利于区分。
~相同参数的Symbol函数的返回值是不相等的。
// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2 // false
// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 // false
~Symbol类型值不能与其它类型的值进行运算,会报错。
let sym = Symbol('My symbol');
"your symbol is " + sym
// TypeError: can't convert symbol to string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string
但是,Symbol 值可以显式转为字符串。
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
另外,Symbol 值也可以转为布尔值,但是不能转为数值。
let sym = Symbol();
Boolean(sym) // true
Number(sym) // TypeError
sym + 2 // TypeError
作为属性名的Symbol
let sym = Symbol('foo')
//第一种写法
let a = {}
a[sym] = "hello"
//第二种写法
let a = {
[sym]: "hello"
}
// 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!' });
a[sym] //"hello"
注意: Symbol值作为对象属性名时,不能用点运算符。
const mySymbol = Symbol();
const a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
上面代码中,因为点运算符后面总是字符串,所以不会当做Symbol类型值作为属性名获取值。