什么是 'global symbol registry'?

What is 'global symbol registry'?

var sym = Symbol();

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

但是 MDN 说:

The above syntax using the Symbol() function will not create a global symbol that is available in your whole codebase. To create symbols available across files and in a global scope-like environment, use the methods Symbol.for() and Symbol.keyFor() to set and retrieve symbols from the global symbol registry.

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

什么是全局符号注册表?

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

所以, 在浏览器世界中,files/realms 的符号可用性范围与全局范围(window 对象)有何不同

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

在您自己的应用程序中,您可以决定某些类型的对象将具有可通过某些符号访问的某些属性。您所有的代码都可以通过 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 对象中的名称冲突几乎完全相同的方式来处理冲突.)

var sym = Symbol();

is creating a new property sym in dictionary(window), which is in global scope, where value can be accessed as window['sym'].

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

What is global symbol registry?

它是一个符号注册表(想想:字典),您可以通过字符串键访问这些符号。在这种情况下,“全局”确实比全局范围更全局,全局符号注册表确实跨越引擎的所有领域。在浏览器中,网页、iframe 和 web worker 都有自己的领域和自己的全局对象,但它们可以通过这个全局注册表共享符号。

而这次分享正是目的所在。如果您另外输入

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 2ality and Symbols and why they're awesome 了解更多示例,包括同样具有全球性的知名符号。

全局符号注册表存在于 window 中的所有 iframe 中。 (由于符号不能在 worker 之间传递,因此没有可观察到的概念表明它在 worker 之间是相同的,除非存在侧通道检查,例如 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来删除全局注册表中的符号,如果您需要手动管理内存,那么手动缓存方式是有益的注册表。