7.2 新的原始类型
ECMAScript 6 引入了一种新的原始类型: symbol 。它能被用作唯一标识的 ID 。通过工厂方法 Symbol() 来创建 symbol 对象(这跟 String
方法返回字符串很类似):
const symbol1 = Symbol();
Symbol()
有一个可选的字符串参数,用作新创建的 symbol 对象的一个描述文本。该文本在 symbol 被转换为字符串(通过 toString()
或者 String()
)的时候用到:
> const symbol2 = Symbol('symbol2');
> String(symbol2)
'Symbol(symbol2)'
Symbol()
方法返回的每一个 symbol 实例都是唯一的,每一个 symbol 对象都有自己的标识:
> Symbol() === Symbol()
false
如果你用 typeof
来检测 symbol 对象,会发现 symbol 是原始类型,因为返回值是一种新的特定于 symbol 对象的类型:
> typeof Symbol()
'symbol'
7.2.1 用作属性键的 symbol
symbol 可以用作属性键:
const MY_KEY = Symbol();
const obj = {};
obj[MY_KEY] = 123;
console.log(obj[MY_KEY]); // 123
类和对象字面量有一个叫做计算属性键的特性:你可以用一个表达式来指定属性键,将表达式放置在中括号里面。如下的对象字面量,使用了计算属性键的方式,让 MY_KEY
成为了键。
const MY_KEY = Symbol();
const obj = {
[MY_KEY]: 123
};
计算键同样适用于方法定义:
const FOO = Symbol();
const obj = {
[FOO]() {
return 'bar';
}
};
console.log(obj[FOO]()); // bar
7.2.2 枚举自有属性键
鉴于现在有一种新的可以用作属性键的值了,那么 ECMAScript 6 中就产生了新的术语:
- 属性键要么是字符串,要么是 symbol 对象。
- 字符串形式的属性键叫做属性名字。
- symbol 对象形式的属性键叫做属性 symbol 。
我们先创建一个对象,然后用这个对象来验证新的自有属性枚举 API 。
const obj = {
[Symbol('my_key')]: 1,
enum: 2,
nonEnum: 3
};
Object.defineProperty(obj,
'nonEnum', { enumerable: false });
Object.getOwnPropertyNames()
忽略 symbol 形式的属性键:
> Object.getOwnPropertyNames(obj)
['enum', 'nonEnum']
Object.getOwnPropertySymbols()
忽略字符串形式的属性键:
> Object.getOwnPropertySymbols(obj)
[Symbol(my_key)]
Reflect.ownKeys()
返回所有类型的键:
> Reflect.ownKeys(obj)
[Symbol(my_key), 'enum', 'nonEnum']
Object.keys()
仅返回可枚举的字符串属性:
> Object.keys(obj)
['enum']
Object.keys
这个名字与新术语(仅列举字符串类型的键)冲突了。现在, Object.names
或者 Object.getEnumerableOwnPropertyNames
会是更好的选择。