Symbol 主要用作唯一属性键 - 一个 symbol 对象不会与任何其他属性键(另一个 symbol 对象或者字符串)冲突。例如,你可以将 Symbol.iterator
作为某个对象的键(键值是一个方法),使其变得可迭代(可以通过 for-of
或者其他语言机制来迭代,更多相关内容可以在有关迭代的章节找到):
const iterableObject = {
[Symbol.iterator]() { // (A)
const data = ['hello', 'world'];
let index = 0;
return {
next() {
if (index < data.length) {
return { value: data[index++] };
} else {
return { done: true };
}
}
};
}
}
for (const x of iterableObject) {
console.log(x);
}
// Output:
// hello
// world
在行 A 处, symbol 对象用作键,键值是一个方法。这个唯一的键使得该对象可迭代,可用于 for-of
循环。
在 ECMAScript 5 中,你可能会使用字符串来表示一些特殊的含义,比如颜色。在 ES6 中,可以使用 symbol ,因为 symbol 总是唯一的:
const COLOR_RED = Symbol('Red');
const COLOR_ORANGE = Symbol('Orange');
const COLOR_YELLOW = Symbol('Yellow');
const COLOR_GREEN = Symbol('Green');
const COLOR_BLUE = Symbol('Blue');
const COLOR_VIOLET = Symbol('Violet');
function getComplement(color) {
switch (color) {
case COLOR_RED:
return COLOR_GREEN;
case COLOR_ORANGE:
return COLOR_BLUE;
case COLOR_YELLOW:
return COLOR_VIOLET;
case COLOR_GREEN:
return COLOR_RED;
case COLOR_BLUE:
return COLOR_ORANGE;
case COLOR_VIOLET:
return COLOR_YELLOW;
default:
throw new Exception('Unknown color: '+color);
}
}
将 symbol 强制(隐式地)转换成字符串会抛出异常:
const sym = Symbol('desc');
const str1 = '' + sym; // TypeError
const str2 = `${sym}`; // TypeError
只能通过显示的方式转换:
const str2 = String(sym); // 'Symbol(desc)'
const str3 = sym.toString(); // 'Symbol(desc)'
禁止强制转换能够避免一些错误,但是也使得 symbol 的使用变得复杂起来。
下面的操作能感知到 symbol 键:
Reflect.ownKeys()
- 通过
[]
访问属性 Object.assign()
下面的操作会忽略掉 symbol 键:
Object.keys()
Object.getOwnPropertyNames()
for-in
循环