(javascript)闭包关闭的封闭范围超过多少

Over how much of its enclosing scope does a (javascript) closure close?

本文关键字:范围 多少 闭包 javascript      更新时间:2023-09-26

当我有一些函数使用来自其封闭作用域的变量并在该作用域(这些作用域)之外使用该函数时,则称为闭包。

是否有关于超过"多少"的封闭范围(s)一个函数必须关闭的任何规范?(或者换句话说,它绝对不需要关闭的次数有多少?)

考虑:

function Outer() {
  var bigGuy = createSomethingHuge();
  var tinyNumber = 42;
  return (function () { /* CONTENTS */ });
}

甚至:

function Layer1() {
  var bigOne = somethingHugePlease();
  var Layer2 = function() {
    var bigToo = morePlease();
    var Layer3 = function() {
       var huge = reallyHuge();
       var tiny = 42;
       return (function () { /* CONTENTS */ });
    };
    return Layer3();
  };
  return Layer2();
}

最后返回的函数关闭这些变量中的哪个?它是否取决于最终函数的内容(eval…?)?

我最感兴趣的是这些情况是否有某种规范,而不是一些特定实现的行为。

我最感兴趣的是这些情况是否有某种规范

ECMAScript规范并没有详细说明这一点。它简单地说,一个函数关闭了整个词法环境,其中包括所有父作用域中的所有变量,组织在所谓的环境记录中。

然而,它并没有指定一个实现应该如何进行垃圾收集——所以引擎必须自己优化它们的闭包——当它们可以推断出一些"闭包"变量永远不需要(引用)时,它们通常会这样做。特别是,如果您在闭包的任何地方使用eval,它们当然不能这样做,并且必须保留所有内容。

不是关于某些特定实现的行为

无论如何,你都想看看JavaScript闭包是如何垃圾收集的,node.js的垃圾收集,关于闭包,LexicalEnvironment和GC以及JavaScript在运行时如何表示闭包和作用域

嵌套函数的作用域链包含对所有外部函数的激活对象的引用,这些外部函数的执行导致了嵌套函数的定义。当外部函数调用返回时,这些激活对象将所有值存储在适当的位置,并继续存在,因为它们位于作用域链中。

因此,根据定义,闭包捕获作用域中的所有变量值。eval("typeof bigGuy");中的'function () {/* CONTENTS */}应该演示这一点。

ECMA标准可能*涵盖了这一点(如果你正在编写一个javascript引擎并且有时间)。一种解决方案可能是在不再需要它们的值时将大变量设置为undefined


*基于10年前ECMA 3.61的读数。计算机科学术语"闭包"没有出现在标准中。闭包的产生必须由读者推断出嵌套函数作用域链是如何构造的隐式结果——这是标准中的。作用域链包括当前执行函数的激活对象、外部函数的激活对象(按相反顺序),然后是全局对象。