(1)概述
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。
Symbol值通过symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有得到字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
let s = Symbol()
typeof s
// 'symbol'
注意,Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象。也就是说,由于Symbol值不是对象,所有不能添加属性。基本上,它是一种类似于字符串的数据类型
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
let s1 = Symbol('foo')
let s2 = Symbol('bar')
s1 // Symbol(foo)
s2 // Symbol(bar)
s1.toString() // 'Symbol(foo)'
s2.toString() // 'Symbol(bar)
(2)Symbol.prototype.description:创建Symbol的时候,可以添加一个描述。
const sym = Symbol('foo')
上面代码中,sym的描述就是字符串foo
但是,读取这个描述需要将Symbol显示转为字符串,即下面的写法。
const sym = Symbol('foo')
sym.description // foo
(3)作为属性名的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'
(4)Symbol.for()、Symbol.keyFor()
1、Symbol.for():接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建一个以该字符串为名称的Symbol值,并将其注册到全局。
let s1 = Symbol.for('foo')
let s2 = Symbol.for('foo')
s1 === s2 // true
注意:Symbol.for()和Symbol()这两种写法,都会生成新的Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的Symbol类型的值而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。比如,如果你调用Symbol.for('cat')30次,每次都会返回同一个Symbol值,但是调用Symbol('cat')30次,会返回30个不同的Symbol值。
Symbol.for('bar') === Symbol.for('bar')
// true
Symbol('bar') === Symbol('bar')
// false
2、Symbol.keyFor:方法返回一个已登记的Symbol类型值的key。
let s1 = Symbol.for('foo')
Symbol.keyFor(s1)
let s2 = Symbol('foo')
Symbol.keyFor(s2)
注意:Symbol.for()为Symbol值登记的名字,是全局环境的,不管有没有在全局环境运行