什么是'全球符号注册表'?

时间:2015-08-08 18:08:41

标签: javascript ecmascript-6 symbols

var sym = Symbol();

window['sym'],已经全局范围

但是MDN说:

  

使用Symbol()函数的上述语法不会创建整个代码库中可用的全局符号。要创建符号跨文件和类似全局范围的环境,请使用方法Symbol.for()Symbol.keyFor()设置和检索全局符号注册表中的符号。

sym已在浏览器的全局范围内,具有上述声明语法。

什么是全球符号注册表?

每个html文档都与window对象绑定。

所以, 在浏览器世界中,文件/领域的符号可用性范围如何与全局范围(window对象不同

3 个答案:

答案 0 :(得分:9)

var sym = Symbol();
     

在字典(sym)中创建一个新属性window,该属性位于全局范围内,其中值可以window['sym']进行访问。

嗯,不。它会创建一个符号并将其分配给名为sym局部变量。只有在全局范围内执行此代码时(对于模块化而言通常不会这样做),它才会在领域的全局对象(js环境)上创建属性。请注意,此全局对象并不总是像网页中那样window,它取决于您的环境。

  

什么是全球符号注册表?

这是一个注册表(思考:字典),可以通过字符串键访问符号。在这种情况下,“全局”意味着甚至比全局范围更全局,全局符号注册表确实涵盖了引擎的所有领域。在浏览器中,网页,iframe和Web工作者都有自己的领域和自己的全局对象,但是他们可以通过这个全局注册表共享符号。

这种共享正是目的。如果你不这样做

var sym1 = Symbol("shared");

var sym2 = Symbol("shared");

在两个地方,然后是sym1 !== sym2。如果您有共享对象,则使用符号 s 作为属性键将创建两个不同的属性。但是,如果你这样做

var sym1 = Symbol.for("shared");

var sym2 = Symbol.for("shared");

然后sym1 === sym2当你使用它时,你将总是获得相同的属性。

有关更多示例,请参阅Crossing realms with symbols on 2alitySymbols and why they're awesome,包括同样具有全局性的众所周知的符号。

答案 1 :(得分:5)

全局符号注册表只是符号实例的便捷全局存储库。如果您愿意,您可以自己实现一个,但内置这样的存储库意味着运行时可以将其用作发布对给定上下文具有特定含义的符号实例的位置。

在您自己的应用程序中,您可以决定某些类型的对象将通过某个符号访问某些属性。您的所有代码都可以通过Symbol.for()找到这些符号:

var SPECIAL_PROPERTY = Symbol.for("mySpecialProperty");
// ...
var specialVal = someObject[SPECIAL_PROPERTY];

因为注册表是全局的,所以无论范围或编译单元如何都可以。

通过使注册表成为运行时的一部分,Node.js之类的环境可以使用符号机制来扩展对象,而不必担心遗留代码会出现问题。就像,如果Node希望能够找到对象使用的内存量,他们可以发明一个符号,将其放入注册表中,并记录注册表项。然后任何代码都可以使用:

var objectSize = myObject[Symbol.for("memory_use")];

(这完全弥补了; Node完全没有意义去做那件特别的事情。)由于符号作为属性键的方式,不知道的代码不会遇到任何奇怪的问题如果它操纵的物体突然开始携带那额外的财产。

(当然,符号注册表本身的名称空间只是一个名称空间,因此必须以与window对象中的名称冲突完全相同的方式处理冲突。)

答案 2 :(得分:1)

全局符号注册表存在于窗口中的所有iframe中。 (由于符号不能通过工人传递,因此除了memory probing之外,没有可观察到的工人之间相同的概念,除非存在旁道检查。)

<script>
document.head.appendChild(document.createElement('iframe'))
.src=`javascript:
  alert(parent.Symbol===Symbol) /*false*/
  ,alert(parent.Symbol.for('a') === Symbol.for('a')) //true
`
</script>

Symbol.for与使用对象引用实现自己的缓存没有太大区别。它只是内置的,因此更方便。您只需执行以下操作即可代替Symbol.for('a')

obj['a']? obj['a'] : obj['a'] = Symbol()`

。并保持参考obj

事实上,由于javascript不提供用于删除全局注册表中的符号的API,因此如果您需要手动管理注册表的内存,则有利于手动缓存方式。