ES6 引入 Symbol 的原因是保证每个属性的名字都是独一无二的,从根本上防止属性名的冲突。
Symbol.prototype.description
Symbol 函数接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时比较容易区分。
let s1 = Symbol('foo')
let s2 = Symbol('bar')
s1 // Symbol(foo)
s2 // Symbol(bar)
相同参数名,并不会让 Symbol 实例相等。
// 没有参数
let s1 = Symbol()
let s2 = Symbol()
s1 === s2 // false
// 有参数
let s1 = Symbol('foo')
let s2 = Symbol('foo')
s1 === s2 // false
ES2019提供了一个实例属性 description,直接返回 Symbol 的描述。
const sym = Symbol('foo')
sym.description // 'foo'
Symbol.for()
Symbol.for(key) 方法会根据给定的 key,来从运行时的 symbol 注册表中找到对应的 symbol。如果找到了,则返回它。否则,新建一个与该键关联的 symbol,并放入全局 symbol 注册表中。
let s1 = Symbol.for('123')
let s2 = Symbol.for('123')
s1 === s2 // true
作为属性名的 Symbol
由于每一个 Symbol 值都是不相等的,这意味着 Symbol 值可以作为标识符,用于对象属性名,从而保证不会出现同名的属性。
let mySymbol = Symbol()
// 第一种写法
let a = {}
a[mySymbol] = 'Hello'
// 第二种写法
let a= {
[mySymbol]:'Hello'
}
// 第三种写法
let a = {}
Object.defineProperty(a, mySymbol, { value:'Hello' })
// 以上写法都得到同样的结果
a[mySymbol] // Hello
💣 Symbol 值作为对象属性名时,不能使用点语法。
const mySymbol = Symbol()
const a = {}
a.mySymbol = 'Hello'
a['mySymbol'] // Hello
上面代码中,因为点运算符后面总是字符串,所以不会读取 mySymbol 作为标识名所指代的那个值,导致对象 a 的属性名实际上是一个字符串,而不是一个 Symbol 值。