javascript - 这种模式是否会导致闭包中的循环引用?

标签 javascript closures circular-reference

我是一个 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's [[Scope]] (a lexical environment)
  • innerFn's [[Scope]]'s environment record
  • the outerVar binding in innerFn's [[Scope]]'s environment record
  • the variable associated with the outerVar binding in innerFn's [[Scope]]'s environment record
  • this variable has innerFn as a property value

但是,由于您无法从 JavaScript 代码访问函数的 [[Scope]] 内部属性,因此您无法从代码中观察到循环引用。

奖金信息

请注意,聪明的实现实际上不会在代码中存储此循环引用,因为它发现 outerVar 从未在任何 outerFn 中使用。 code> 的子函数。当 outerFn 结束时,可以安全地完全忘记 outerVar 的绑定(bind)。更有趣的是,使用 eval 无法进行这种优化,因为无法识别 innerFn 是否会使用 outerVar:

function outerFn() {
  var outerVar = {};
  function innerFn(codeStr) {
    alert(eval(codeStr));    // will `codeStr` ever be "outerVar"?
  }
  return innerFn;
}

关于javascript - 这种模式是否会导致闭包中的循环引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26256986/

相关文章:

javascript - onload、onunload、onbeforeunload 之间的区别

closures - 如何在 Rust 的结构中存储闭包?

javascript - 拆除 JavaScript 中的闭包

rest - Symfony序列化器-设置循环引用全局

javascript - 防止 JavaScript window.getSelection() 循环引用

javascript - 如何通过网络使用 firebase 云消息传递

javascript - 在 Javascript 中将特殊字符编码为 Base64,并在 PHP 中使用 base64_decode() 进行解码

javascript - 嵌套模型通过javascript添加和销毁

javascript - 一个简单的函数闭包问题——更新计数的计数器函数

.net - 在 .NET 框架中遇到自递归程序集引用