javascript 什么是“全局符号注册表”?

lmyy7pcs  于 2023-02-15  发布在  Java
关注(0)|答案(3)|浏览(140)
var sym = Symbol();

window['sym'],它已经是全局作用域
但MDN说:
以上使用Symbol()函数的语法不会创建在整个代码库中可用的全局符号。要创建在文件间和类似全局作用域的环境中可用的符号**,请使用方法Symbol.for()Symbol.keyFor()设置符号并从全局符号注册表中检索符号。
sym已在浏览器的全局范围内,具有上述声明语法。
什么是全局符号注册表?
每个html文档都与window对象绑定。
那么,在浏览器世界中,跨文件/领域的符号可用性范围与全局范围(window对象)有何不同?

idv4meu8

idv4meu81#

var sym = Symbol();

正在字典(window)中创建一个新属性sym,该属性位于全局范围内,其值可以作为window['sym']访问。
当然不是,它创建了一个符号,并将其赋给一个名为sym的 * 局部变量 *,只有当你在全局范围内执行这段代码时(由于模块化的原因,你通常不会这样做),它才会在你的领域(js环境)的全局对象上创建一个属性,请注意,这个全局对象并不总是像网页中的window,它取决于你的环境。
什么是全局符号注册表?
它是一个注册表(想想看:dictionary),用于你可以通过字符串键访问的符号。在这里,"global"意味着比全局作用域更全局,全局符号注册表覆盖了你引擎的所有领域。在浏览器中,网页、iframe和web工作者都有自己的领域,有自己的全局对象,但是他们可以通过这个全局注册表共享符号。
而这种分享正是目的所在。如果你不把

var sym1 = Symbol("shared");

var sym2 = Symbol("shared");

如果你有一个共享对象,使用符号 * s * 作为属性键将创建两个不同的属性。

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

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

然后是sym1 === sym2,当你使用它时,你会得到相同的属性。
更多例子参见 * 用符号跨越界域 * 和 * 符号和为什么它们很棒 *,包括同样全球化的著名符号。

wyyhbhjk

wyyhbhjk2#

全局符号注册中心只是一个方便的符号示例的全局存储库,如果愿意,您可以自己实现一个,但是内置这样的存储库意味着运行时可以将其用作发布符号示例的地方,这些符号示例对于给定的上下文具有特定的意义。
在你自己的应用程序中,你可以决定某些类型的对象将具有通过某些符号访问的某些属性,你所有的代码都可以通过Symbol.for()找到这些符号:

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

因为注册表是全局的,所以无论范围或编译单元如何,它都可以工作。
通过使注册表成为运行时的一部分,像Node.js这样的环境可以使用符号机制来扩展对象,而不必担心给遗留代码带来问题。例如,如果Node想让你知道一个对象使用了多少内存,他们可以发明一个符号,把它放在注册表中,并记录注册表项。任何代码都可以使用它:

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

(That完全是编出来的节点做那个特定的事情可能根本没有意义。)由于符号作为属性键的工作方式,如果代码操作的对象突然开始携带那个额外的属性,不知道它的代码将不会遇到任何奇怪的问题。
(Of当然,符号注册表本身的名称空间只是一个名称空间,因此必须以与我们处理window对象中的名称冲突几乎完全相同的方式来处理冲突。)

cbjzeqam

cbjzeqam3#

全局符号注册表存在于窗口中的所有iframe中。(因为符号不能在工作者之间传递,所以没有观察到它在工作者之间相同的概念,除非存在侧通道检查,例如通过内存探测。

<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来删除全局注册表中的符号,因此如果您需要手动管理注册表的内存,则使用手动缓存的方式进行删除是有益的。

相关问题