概述
ES5中的对象属性名都是字符串,如果我们使用了一个他人提供的对象,又需要为该对象添加新的方法(mixin模式),新的方法可能会与现有的方法产生冲突,ES6引入了新的数据类型Symbol
来保证每个属性的名字是独一无二的。
至此,JavaScript共有七种数据类型:undefined
、null
、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)、Symbol
。Symbol的值是通过Symbol
函数生成的,不能使用new
。
let s = Symbol('foo');
typeof s // "symbol"
s1.toString() // "Symbol(foo)"
let s1 = Symbol('foo');
s === s1 // false
作为属性名的Symbol
let a1 = Symbol.for('abc');
let obj = {
[a1]: '123',
'abc': 345,
'c': 456
};
console.log('obj', obj);
Symbol的值作为对象属性名时,不能使用点运算符。此时,该属性是公开属性,不是私有属性。
Symbol类型还可以定义一组常量,保证这组常量的值都是不相等的。
const COLOR_RED = Symbol();
const COLOR_GREEN = Symbol();
function getComplement(color) {
switch (color) {
case COLOR_RED:
return COLOR_GREEN;
case COLOR_GREEN:
return COLOR_RED;
default:
throw new Error('Undefined color');
}
}
属性名的遍历
Symbol作为属性名,不会被for...in
、for...of
遍历,也不会被Object.keys()
、Ojbect.getOwnPropertyNames()
、JSON.stringify()
返回。
它可以通过Object.getOwnPropertySymbols()
遍历,该方法赶回一个数组,也可以通过Reflect.ownKeys
方法遍历:
let a1 = Symbol.for('abc');
let obj = {
[a1]: '123',
'abc': 345,
'c': 456
};
console.log('obj', obj);
for (let [key, value] of Object.entries(obj)) {
console.log('let of', key, value);
}
Object.getOwnPropertySymbols(obj).forEach((item) => console.log(obj[item]));
Reflect.ownKeys(obj).forEach((item) => console.log('ownkeys', item, obj[item]));
Symbol.for(), Symbol.keyFor()
通过Symbol.for
方法可以重新使用同一个Symbol值,它的参数是一个字符串,然后搜索是否有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则会新建并返回一个以该字符串为名称的Symbol值。
let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
s1 === s2 // true
Symbol.keyFor
方法返回一个已登记的Symbol类型值的key
。
let s1 = Symbol.for('foo');
Symbol.keyFor(s1) // "foo"
let s2 = Symbol('foo');
Symbol.keyFor(s2) // undefined
内置的Symbol值
ES6提供了11个内置的Symbol值,指向语言内部的使用方法。
-
Symbol.hasInstance
-
Symbol.isConcatSpreadable
-
Symbol.species
-
Symbol.match
-
Symbol.replace
-
Symbol.search
-
Symbol.split
-
Symbol.iterator
对象进行
for...of
循环时,会调用此方法。 -
Symbol.toPrimitive
-
Symbol.toStringTag
-
Symbol.unscopables
具体使用方法和介绍可以参考阮一峰老师的教程 内置的Symbol值。
网友评论