符号

多个接口可能为不同的事物使用相同的属性名称。 例如,我可以定义一个接口,其中toString方法应该将对象转换为一段纱线。 一个对象不可能同时满足这个接口和toString的标准用法。

这是一个坏主意,这个问题并不常见。 大多数 JavaScript 程序员根本就不会去想它。 但是,语言设计师们正在思考这个问题,无论如何都为我们提供了解决方案。

当我声称属性名称是字符串时,这并不完全准确。 他们通常是,但他们也可以是符号(symbol)。 符号是使用Symbol函数创建的值。 与字符串不同,新创建的符号是唯一的 - 你不能两次创建相同的符号。

  1. let sym = Symbol("name");
  2. console.log(sym == Symbol("name"));
  3. // → false
  4. Rabbit.prototype[sym] = 55;
  5. console.log(blackRabbit[sym]);
  6. // → 55

Symbol转换为字符串时,会得到传递给它的字符串,例如,在控制台中显示时,符号可以更容易识别。 但除此之外没有任何意义 - 多个符号可能具有相同的名称。

由于符号既独特又可用于属性名称,因此符号适合定义可以和其他属性共生的接口,无论它们的名称是什么。

  1. const toStringSymbol = Symbol("toString");
  2. Array.prototype[toStringSymbol] = function() {
  3. return `${this.length} cm of blue yarn`;
  4. };
  5. console.log([1, 2].toString());
  6. // → 1,2
  7. console.log([1, 2][toStringSymbol]());
  8. // → 2 cm of blue yarn

通过在属性名称周围使用方括号,可以在对象表达式和类中包含符号属性。 这会导致属性名称的求值,就像方括号属性访问表示法一样,这允许我们引用一个持有该符号的绑定。

  1. let stringObject = {
  2. [toStringSymbol]() { return "a jute rope"; }
  3. };
  4. console.log(stringObject[toStringSymbol]());
  5. // → a jute rope