此模式是否会导致闭包中出现循环引用
Does this pattern causes a circular reference in a closure?
我是javascript新手。我最近正在学习javascript及其出色的属性闭包。
但我对下面的代码片段感到困惑。
function outerFn() {
var outerVar = {};
function innerFn() {
alert('haha');
}
outerVar.pro = innerFn;
return innerFn;
}
我认为它不是innerFn和outerVar之间的循环引用,因为只有outerVar-pro指向innerFn。
但一些书指出,它仍然是一个循环参考。
有人能解释一下它是否是循环引用吗?提前谢谢。
此可能在JavaScript引擎中导致循环引用(因为innerFn
的父词法环境包括outerVal
,其中包括innerFn
),但它不会导致JavaScript代码可以观察到的循环引用。
当outerFn
运行时,会定义函数innerFn
。在JavaScript中,新定义的函数可以访问范围中当前可访问的所有变量,因此innerFn
内部的代码可以访问outerVar
:
function outerFn() {
var outerVar = {};
function innerFn() {
alert(outerVar); // totally fine
}
return innerFn;
}
在ECMAScript术语中,这是因为每个函数都有一个词法环境,用于解析称为[[Scope]]
的变量标识符。新定义的函数的[[Scope]]
内部属性设置为其父函数的词法环境。因此,这里,innerFn
的[[Scope]]
是outerFn
的词汇环境,其中包含对outerFn
的引用。
在ECMAScript术语中,循环引用路径为:
innerFn
innerFn
的[[Scope]]
(一种词汇环境)innerFn
的[[Scope]]
的环境记录innerFn
的[[Scope]]
的环境记录中的outerVar
绑定- 与
innerFn
的[[Scope]]
的环境记录中的outerVar
绑定关联的变量- 该变量的属性值为
innerFn
但是,由于无法从JavaScript代码中访问函数的[[Scope]]
内部属性,因此无法从代码中观察到循环引用。
奖金信息
请注意,一个聪明的实现实际上不会在代码中存储这个循环引用,因为它可以看到outerVar
从未在outerFn
的任何子函数中使用过。当outerFn
结束时,可以安全地完全忘记对outerVar
的绑定。值得注意的是,eval
不可能进行此优化,因为无法识别innerFn
是否会使用outerVar
:
function outerFn() {
var outerVar = {};
function innerFn(codeStr) {
alert(eval(codeStr)); // will `codeStr` ever be "outerVar"?
}
return innerFn;
}
- 如何处理javascript中的循环引用,类似于Excel提供迭代限制的方式
- 装饰$errorProvider时的循环引用
- 使用javascript点击事件的循环引用
- 使用 jQuery 将 HTML 文本抓取到 JSON 中,但由于循环引用而无法字符串化
- 为什么$().map生成循环引用
- 这是否在javascript中创建循环引用
- JS - 数字循环引用
- 如何在 JavaScript 和浏览器中处理循环引用
- 可观察量相互依赖以获取自己的值 - 循环引用
- 循环引用似乎在事件处理程序函数中不起作用
- JavaScript <-> DOM 循环引用问题的精确解释
- jQuery data()如何破坏循环引用
- 多次循环引用对象,将其属性复制到Javascript/Angularjs中的其他对象
- 此模式是否会导致闭包中出现循环引用
- 我应该如何在JavaScript中设置循环引用
- javascript函数之间的循环引用
- 循环引用木偶.js
- jQuery.从循环引用扩展safe
- 循环引用阻塞了jsonwebtoken.JSON.stringify的签名原因
- 字符串化一个循环引用对象的浅拷贝