Symbol.for(字符串) 在 ECMAScript 6 中

Symbol.for(string) in ECMAScript 6

我花了一段时间,但我终于明白了 ECMAScript 6 中符号的用途是什么:在将属性附加到共享对象时避免名称冲突 - HTML 元素,例如(如果您遇到同样的问题,我建议 this article。)

但后来我偶然发现了 Symbol.for()。显然 ECMAScript 6 将维护一个全局符号注册表,您可以通过提供符号描述来使用此功能查询。再来?如果我使用符号来避免名称冲突,为什么我要让我自己的代码以外的代码使用它们? (*) 我将如何避免在该全球注册表中发生名称冲突?符号的共享似乎完全颠覆了这个概念,而全球注册则加倍如此。

(*) 是的,我知道符号并不是 真正 私有的,但这不是重点。

如果您不希望您的符号在 GlobalSymbolRegistry 中可用,请不要使用 Symbol.for

仅当您想让其他代码使用您的符号时才使用它。

在下面的示例中,我创建了一个符号来将数据存储在 DOM 个元素中。我可能希望所有其他代码(例如 internal raw uncompiled handlers)读取该数据。所以我让这个符号在全球可用。

var sym = Symbol.for('storeDataInDOM');
document.querySelector('button')[sym] = 'Hello, world!';
<button onclick="alert(this[Symbol.for('storeDataInDOM')])">Click me</button>

这就像创建全局变量:一般应避免,但有其优点。但是用符号而不是字符串。

If I use symbols to avoid name collisions, why would I want code other than my own to use them?

这不是符号的唯一用例。另外两个最重要的是:

  • 它们不会与字符串键控属性冲突
  • 通常的机制不会列举它们

Sharing of symbols seems to completely subvert the concept and a global registry doubly so.

不一定。来自 that article you read: "The registry is useful when multiple web pages, or multiple modules within the same web page, need to share a symbol." The best example for these are the intrinsic symbols - they guarantee interoperability across realms, that's why the 的权利比您的全球范围更全球化。

例如,您可能有一个加载到网页中的库、一个 iframe 和一个网络工作者。如果您在这些环境(领域)之间共享数据,则库的所有三个实例都需要使用 相同 符号。

不同库之间也确实需要互操作性,它们甚至可能彼此不了解。 transducers, algebraic structures or promises. Would ES6 already be in use, all of these would have agreed on common names in the global symbol registry, instead of relying on strings like thesethen 方法就是很好的例子。

Another good example 将是由您的引擎定义的自定义挂钩,例如一个 Symbol.inspect = Symbol.for("inspect"),您可以使用它来定义要由 console.log 使用的自定义字符串化行为。不可否认,该符号不一定需要通过全局符号注册表提供,它也可以放在特定的库对象上(例如 console.inspect = Symbole("console.inspect"))。

And how would I avoid name collisions in that global registry?

就像您之前对属性或全局模块对象所做的一样:通过使用非常长、非常具有描述性的名称 - 或者出于善意。还有.

我发明了 Symbol.for() 通话最有用的功能。如果您的代码中使用符号,有时很难在调试时使用 条件断点 。例如,如果变量等于符号类型的值并且该值绑定在不同的模块中,则需要捕获。第一个困难的方法是将这个值用作常量并将其从该模块中导出。在这种情况下,断点的条件将是:

catchedVariable === exportedSymbolConst

但最简单的方法是临时更改模块内部的代码,将.for添加到Symbol。然后你可以写条件:

catchedVariable === Symbol.for('string_key')

成功调试后,您只需删除 .for 部分即可将代码改回原来的状态。