1.概述
ES6 引入了一种新的数据类型 Symbol,是 JavaScript 的第七种数据类型,前六种为:null、undefined、boolean、number、string、object。Symbol 数据类型能保证每个属性的名字是独一无二的。
Symbol 值通过 symbol 函数生成,注意此时不能用 new 来生成,这是因为 Symbol 类型是原始数据类型,不是对象类型 ,因此它也不能添加属性。基本上 Symbol 类型类似于字符串类型。
let s = Symbol();
typeof s // "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)"
如果 Symbol 的参数是一个对象,则会调用对象的 toString()将其转换为字符串后才生成一个 Symbol 值。
const obj = {
toString(){
return "abc";
}
};
const s = Symbol(obj);
s //Symbol(abc)
Symbol 函数的参数只是对当前 Symbol 值的描述,因此参数相同的 Symbol 函数的返回值是不相等的。
let s1 = Symbol();
let s2 = Symbol();
s1 === s2; //false
Symbol 值不能与其他类型的值进行运算,否则会报错
let s = Symbol("hello");
s + "world"; //TypeError:cannot convert symbol to string
'${s} world'; //TypeError:cannot convert symbol to string
Symbol 值除了可以用 toString() 转换为字符串外,还可用用 Boolean(变量名) 转为布尔类型,但是不能转为数值类型。
2. Symbol.prototype.description :直接返回 Symbol 的描述
let s = Symbol("foo");
s.description //"foo"
3. 作为对象的属性名
由于每一个 Symbol值都是不相等的,故其可以当做标识符,用于对象的属性名,就保证不会出现同名的属性。Symbol 作为属性名时,不能用点运算符。作为属性名,Symbol 为公开属性,不是私有属性。
//例1
let sym = Symbol();
//第一种写法
let a = {};
a[sym] = "hello";
//第二种写法
let a = {
[sym] = "hello";
};
//第三种写法
let a = {};
Object.defineProperty(a,sym,{value:"hello"});
//以上都会得到一样的结果
a[sym] //"hello"
//例2
let sym = Symbol();
let obj = {
[sym]:function(args){...} // 还可以这么写 [sym](args){...}
};
obj[sym](123);
4. 属性名的遍历:Object.getOwnPropertySymbols() 返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。Reflect.ownKeys() 可以返回任何类型的属性名。
5. Symbol.for(),Symbol.keyFor()
Symbol.for():有时我们需要用到同一个 Symbol 值,Symbol.for() 可以做到这一点。它接受一个字符串为参数,然后搜索有没有以该参数名作为属性名的 Symbol 值。若有,就返回这个 Symbol 值,否则就新建一个以这个参数名作为属性名的 Symbol 值,并将其注册到全局。注意,Symbol.for() 为 Symbol 值登记的名字,是全局环境的,不管其有没有在全局环境中运行。
let s1 = Symbol.for();
let s2 = Symbol.for();
s1 === s2 //true
Symbol.keyFor():返回一个已登记的 Symbol 类型的 key。
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) //"foo"
let s2 = Symbol("foo");
Symbol.keyFor(s2) //undefined 因为 s2 未登记