我花了一段时间,但我终于弄明白ECMAScript 6中符号的用途是什么:在将属性附加到共享对象时避免名称冲突 - 例如HTML元素(如果你仍然坚持同一个问题,我建议this article。)
然后我偶然发现了Symbol.for()。显然,ECMAScript 6将维护一个全局符号注册表,您可以通过提供符号描述来使用此函数进行查询。再来?如果我使用符号来避免名称冲突,为什么我要使用除我自己之外的代码来使用它们呢? (*)我如何避免全局注册表中的名称冲突?分享符号似乎完全颠覆了这个概念,而全球注册表则完全颠覆了这一概念。
(*)是的,我知道符号并非真正私有,但除此之外还有。
答案 0 :(得分:11)
如果您不希望您的符号在GlobalSymbolRegistry中可用,请不要使用Symbol.for
。
如果您想允许其他代码使用您的符号,请仅使用它。
在下面的示例中,我创建了一个符号来在DOM元素中存储数据。我可能希望其他所有代码(例如Using Step function in animate to transform-rotate an element)都能读取该数据。所以我将符号全局化。
var sym = Symbol.for('storeDataInDOM');
document.querySelector('button')[sym] = 'Hello, world!';

<button onclick="alert(this[Symbol.for('storeDataInDOM')])">Click me</button>
&#13;
它就像创建全局变量:一般应该避免,但有其优点。但是用符号代替字符串。
答案 1 :(得分:6)
如果我使用符号来避免名称冲突,为什么我要使用除我自己之外的代码来使用它们?
这不是符号的唯一用例。其中最重要的两个是:
分享符号似乎完全颠覆了这个概念,并且全面地反映了这个概念。
不一定。从that article开始,您读到:“当多个网页或同一网页中的多个模块需要共享符号时,注册表非常有用。”这些的最佳示例是内在符号 - 它们保证跨领域的互操作性,这就是为什么global symbol registry比全局范围更全局化。
例如,您可能有一个加载在网页中的库,一个iframe和一个Web工作者。如果您在这些环境(领域)之间共享数据,则库的所有三个实例都希望使用相同的符号。
实际上还需要不同库之间的互操作性,这些库可能甚至不知道彼此。好例子是transducers,algebraic structures或promises。 ES6是否已经在使用中,所有这些都会在全局符号注册表中就通用名称达成一致,而不是依赖于these或then
方法等字符串。
Another good example将是您的引擎定义的自定义挂钩,例如一个Symbol.inspect = Symbol.for("inspect")
,可用于定义console.log
使用的自定义字符串化行为。无可否认,该符号不一定需要通过全局符号注册表提供,也可以放在该特定的库对象上(例如console.inspect = Symbole("console.inspect")
)。
我如何在全局注册表中避免名称冲突?
就像您之前使用属性或全局模块对象一样:使用非常长的,非常具有描述性的名称 - 或者善意。还有some naming conventions。
答案 2 :(得分:0)
我发明了Symbol.for()
通话最有用的功能。如果您的代码中有时使用符号,则有时在调试时很难使用条件断点。例如,您需要捕获变量是否等于符号类型的值,并且该值绑定在其他模块中。第一个困难的方法是将该值用作常量,然后从该模块导出它。在这种情况下,断点的条件将如下所示:
catchedVariable === exportedSymbolConst
但是最简单的方法是临时更改模块内部的代码,将.for
添加到Symbol
。然后,您可以编写条件:
catchedVariable === Symbol.for('string_key')
成功调试之后,您将只需删除.for
部分即可将代码改回。