(javascript)闭包关闭多少封闭范围?

时间:2015-09-01 06:47:46

标签: javascript garbage-collection closures

当我有一些函数使用其封闭范围内的变量并在该范围之外使用该函数(这些范围)时,这称为闭包。

是否有关于"多少"其封闭范围的功能必须关闭? (或者换句话说,超过"多少"它绝对需要关闭?)

考虑:

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

最终返回的函数关闭了哪些变量?它取决于最终函数的内容({{1}} ......?)?

我最感兴趣的是这些案例是否有某种规范,而不是某些具体实施的行为。

2 个答案:

答案 0 :(得分:2)

  

我最感兴趣的是这些案例是否有某种规范

ECMAScript specification并没有详细说明这一点。它只是说一个函数关闭整个lexical environment,其中包括所有父作用域中的所有变量,这些变量在所谓的环境记录中组织。

然而,它没有具体说明一个实现应该如何进行垃圾收集 - 因此引擎必须自己优化它们的关闭 - 而且它们通常会做,当它们可以推断出一些关闭"关闭"永远不需要变量(引用)。具体来说,如果你在闭包中的任何地方使用eval,他们当然不能这样做,并且必须保留所有内容。

  

与某些特定实现的行为无关

无论如何,您要查看How JavaScript closures are garbage collectedgarbage collection with node.jsAbout closure, LexicalEnvironment and GCHow are closures and scopes represented at run time in JavaScript

答案 1 :(得分:0)

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

因此,根据定义,闭包捕获范围内的所有变量值。 &{39; function(){/ * CONTENTS * /}中的eval("typeof bigGuy");应证明这一点。

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

<小时/> *基于十年前阅读ECMA 3.61。计算机科学术语&#34;关闭&#34;没有出现在标准中。闭包的产生必须由读者推断,作为嵌套函数作用域链如何构造的隐含结果 - 这是标准中的。范围链包括当前正在执行的函数的激活对象,外部函数&#39;激活对象的顺序相反,后跟全局对象。无法在用户代码中修改范围链。