7.1 概览

7.1.1 用途1:唯一属性键

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 循环。

7.1.2 用途2:用常量代表特殊的含义

在 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);
    }
}

7.1.3 陷阱:不能将 symbol 强制转换成字符串

将 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 的使用变得复杂起来。

7.1.4 哪些跟属性相关的操作能感知到 symbol 键?

下面的操作能感知到 symbol 键:

  • Reflect.ownKeys()
  • 通过 [] 访问属性
  • Object.assign()

下面的操作会忽略掉 symbol 键:

  • Object.keys()
  • Object.getOwnPropertyNames()
  • for-in 循环

results matching ""

    No results matching ""