ECMA-262-v6中“符号”类型的含义是什么?

时间:2015-06-18 15:08:21

标签: javascript symbols ecmascript-6

ECMA-262-v6中“符号”类型的含义是什么?对象键的快速路径实现?它在底层做了什么 - 用基本数据保证不可变的保证哈希它?

2 个答案:

答案 0 :(得分:9)

符号是替换魔术名称的私钥。它们阻止使用简单的字符串来引用该字段,因此只有具有该符号的消费者才能获得访问权。

某些符号用于指示运行时的特定行为(如Symbol.iterator,其行为与预共享秘密非常相似),而其他符号可由库分配并用于有效隐藏字段。

通常,符号旨在替代魔法名称。您可以分配符号const foo = Symbol()并有选择地传递该符号,而不是简单地称为“foo'”。这允许运行时在启动时分配Symbol.iterator,并保证任何尝试实现迭代的人都以一致的方式这样做。

运行时可以使用符号来优化对某些字段的访问,如果它感觉需要,但不是必须的。

您可以使用符号将消费者引导至特定方法,具体取决于其用途。例如,如果您有一个可以返回同步迭代或生成器的库,则根据客户端的异步支持,您可以:

const syncIterable = Symbol();
const asyncIterable = Symbol();

class Foo {
  static getIterable(async = false) {
    return async ? asyncIterable : syncIterable;
  }

  [syncIterable]() {
    return new SyncFoo();
  }

  [asyncIterable]() {
    return new AsyncFoo();
  }
}

let foo = new Foo();
for (let x of foo[Foo.getIterable(true)]()) {
  // could be a iterator, could be a generator
}

这是一个相当人为的例子,但展示了图书馆如何使用符号有选择地提供对用户的访问。

答案 1 :(得分:1)

它们几乎可以帮助我们进行命名冲突。每当您想以独特的方式创建属性时,都应该获取符号。

看看我的例子

const bert = Symbol('Bert');

“ Bert”

  

注意:这不是一个值,这就是他们所说的描述符,   因为符号本身只是唯一的标识符。所以如果你是   可视化一个符号,也许您可​​以可视化为   像这样的东西“ sdfasdfa2342134987fgsdfgsdf9808fsfgsd”绝对   唯一的符号,以便您可以确保它永远不会覆盖   那里的任何其他代码。

这很酷,如果我创建另一个符号,例如

const person = Symbol('Bert')

您可以看到我再次使用了“ Bert”。因为我将它们描述为同一件事,所以它们会一样吗?

const bert = Symbol('Bert');
const person = Symbol('Bert');


console.log(bert);
console.log(person);
console.log(bert === person);
console.log(bert == person);
enter image description here

如果您正在创建类的对象,这可能会很有用。

  const classRoom = {
    'Mia' : { grade: 50, gender: 'female' },
    'Gilbert': { grade: 80, gender: 'male' },
    'Gilbert' { grade: 80, gender: 'male' },
  };

但是随后您有另一个名为Gilbert的人,因此在那里发生了命名冲突。因此,想象一下您是否正在处理数百万个数据。因此,我们可以使用符号来命名他们,而不是使用人名或使用某种唯一标识符。

  const classRoom = {
    [Symbol('Mia')] : { grade: 50, gender: 'female' },
    [Symbol('Gilbert')]: { grade: 80, gender: 'male' },
    [Symbol('Gilbert')]: { grade: 80, gender: 'male' },
  };

关于符号的另一件事是它们不可枚举,这意味着如果我愿意的话,我们无法遍历它们

  for (const person in classRoom) {
    console.log(person);
  }

我什么也没得到。

如果您确实要访问所有符号,因为它们包含您要获取的某些信息,则可以使用对象方法。

  const syms = Object.getOwnPropertySymbols(classRoom);
  const data = syms.map(sym => classRoom[sym]);
  console.log(data);