JavaScript数据类型 - Symbol
ES5:对象的属性名只能是字符串,当给对象添加新属性时,很容易造成属性名冲突,从而覆盖了原有的属性。
ES6:所以ES6中引入了symbol数据类型,他表示独一无二的值,避免了属性名的冲突,此时对象的属性名可由字符串类型或者symbol类型来定义。
symbol是一种基本数据类型,通过Symbol()函数来返回symbol类型的值,具有唯一性。
语法:Symbol([description])
参数:description可选,字符串类型,表示对symbol的描述,调试时更容易区分。
一、作为普通变量使用
var symbol1 = Symbol();
var symbol2 = Symbol("2");
var symbol2c = Symbol("2");
console.log(typeof symbol1); // symbol
console.log(symbol2 === symbol2c); // false
注意:
1. 不可使用new Symbol()来创建实例,否则会报TypeError,
围绕原始数据类型创建一个显式包装器对象从 ECMAScript 6 开始不再被支持。 然而,现有的原始包装器对象,如 new Boolean
、new String
以及new Number
,因为遗留原因仍可被创建。
2. Symbol
函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol
函数的返回值是不相等的。
3. Symbol值不能与其他类型的值进行运算,除非将symbol值转换为字符串,如String(symbol2)或者symbol2.toString()。
4. Symbol值可转换为布尔值,例如Boolean(symbol2)为true,!symbol2为false,Symbol值只能转换为字符串值或者布尔值。
二、作为对象属性名使用
var sName = Symbol("name");
var obj = {
[sName]: "lily",
sAge: 18
}
// 另外也可这样赋值
// obj[sName] = "lily";
// Object.defineProperty(a, mySymbol, { value: 'Hello!' });
console.log(obj); // {sAge: 18, Symbol(name): "lily"}
console.log(obj[sName]); // lily
注意:
1. Symbol作为对象属性名时,不能使用点运算符,使用点运算符后,这个属性名就是一个普通字符串了,而不是Symbol类型。
2. Symbol属性名具有隐藏性,是不可枚举属性,所以这个属性不能使用for...in、for...of、Object.keys()
、Object.getOwnPropertyNames()
、JSON.stringify()
等方法访问到,
可以通过创建时的原始 symbol 值访问到,或者通过遍历 “Object.getOwnPropertySymbols()
” 返回的数组中得到。
var sName = Symbol("name"); var obj = { [sName]: "lily", sAge: 18 }
console.log(obj[sName]); // lily
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(name)]
另一个新的 API,Reflect.ownKeys()
方法可以返回所有类型的键名,包括常规键名和 Symbol 键名。
var sName = Symbol("name"); var obj = { [sName]: "lily", sAge: 18 } Reflect.ownKeys(obj); // ["sAge", Symbol(name)]
三、获取description的属性
es2019提供了获取Symbol描述的方法
var sName = Symbol("name"); console.log(sName.description); // name
四、Symbol.for(),Symbol.keyFor()
1. 有时,我们希望重新使用同一个 Symbol 值,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 值。
2. Symbol.keyFor()
方法返回一个已登记的 Symbol 类型值的key
。
let s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" let s2 = Symbol("foo"); Symbol.keyFor(s2) // undefined
参考文献:
http://es6.ruanyifeng.com/#docs/symbol
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Symbol