ECMAScript6-Symbol

67 阅读1分钟

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 值。