ES6:关于Symbol,你了解多少?
概述
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。也就是说,现在对象属性名可以有两种类型:一种是原来就有的字符串,另一种就是新增的Symbol类型,可以保证不会与其他属性名冲突。
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了再控制台显示,或者转化为字符串时比较容易区分。
let s = Symbol('foo');
typeof s //symbol
s //Symbol(foo)
s.toString() //"Symbol(foo)"
String(s) //"Symbol(foo)"
若Symbol的参数是对象,则会调用对象的toString方法,将其转化为字符串,再生成symbol。
const obj = {
toString(){
return 'abc'
}
}
let sym = Symbol(obj);
sym //Symbol(abc)
作为属性名的Symbol
由于每个Symbol值都是不相等的,意味着Symbol值可以作为标识符用于对象的属性名,保证不会出现同名属性。但是,Symbol属性不允许用点运算符访问
var mysym = Symbol();
//下面三种写法都可以
var a = {}
a[mysym] = 'hello';
var a = {
[mysym] : 'hello'
};
var a = {}
Object.defineProperty(a,mysym,{value: 'hello'});
//相同的结果
a[mysym] //'hello'
属性名的遍历
Symbol作为属性名,该属性不会出现在for... in
或者for...of
中,也不会被Object.keys()
、Object.getOwnPropertyNames()
返回。但是,有一个Object.getOwnPropertySymbols
方法会返回指定对象的Symbol属性名。
var obj = {};
var a = Symbol('a');
var b = Symbol('b');
obj[a] = "hello";
obj[b] = "world";
var symbols = Object.getOwnPropertySymbols(obj);
symbols //[Symbol(a),Symbol(b)]
另一个新的 API:Reflect.ownKeys
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
let obj = {
[Symbol('a')] : 1,
num : 2
}
Reflect.ownKeys(obj) //["num",Symbol(a)]
出现了!让独一无二共享!
有时,我们希望重新使用同一个Symbol值, Symbol.for
方法可以做到这一点。它接受 一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建井返回一个以该字符串为名称的 Symbol 值。
var s1 = Symbol.for('foo');
var s2 = Symbol.for('foo');
s1 === s2 //true
Symbol.for('foo') === Symbol.for('foo') //true
Symbol('foo') === Symbol('foo') //false