(javascript) 闭包关闭了它的多少封闭范围?
Over how much of its enclosing scope does a (javascript) closure close?
当我有一些函数使用其封闭范围内的变量并在此范围(这些范围)之外使用该函数时,这称为闭包。
是否有关于函数必须关闭超过 "how much" 个封闭范围的规范? (或者,换句话说,超过 "how less" 它绝对需要关闭?)
考虑:
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
...?)?
我最感兴趣的是是否有针对这些情况的某种规范,而不是某些特定实现的行为。
嵌套函数的作用域链包含对所有外部函数的激活对象的引用,这些外部函数的执行导致嵌套函数的定义。当外部函数调用返回并继续存在时,这些激活对象将所有值存储在适当的位置,因为它们在作用域链中。
因此,根据定义,闭包捕获范围内的所有变量值。 eval("typeof bigGuy");
在 'function () { /* CONTENTS */ } 中应该证明这一点。
ECMA 标准可能*涵盖了这一点(如果您正在编写 javascript 引擎并且有时间)。一个解决方案可能是在不再需要它们的值时将大型变量设置为 undefined
。
*基于十年前阅读 ECMA 3.61。计算机科学术语 "closure" 没有出现在标准中。闭包的产生必须由 reader 推断为嵌套函数作用域链构建方式的隐含结果——这在标准中。作用域链包括当前正在执行的函数的激活对象,外部函数的激活对象以相反的顺序,然后是全局对象。作用域链不能在用户代码中修改。
I'm mostly interested into whether there is some kind of specification for these cases
ECMAScript specification does not really detail this. It simply says that a function closes over the whole lexical environment 包括所有父作用域中的所有变量,组织在所谓的环境记录中。
然而它并没有指定一个实现应该如何进行垃圾收集——所以引擎确实必须自己优化它们的闭包——它们通常会这样做,当它们可以推断出一些 "closed over" 变量永远不需要时(参考)。具体来说,如果您确实在闭包中的任何地方使用 eval
,他们当然不能这样做,并且必须保留所有内容。
not so much about the behavior of some specific implementation
无论如何,你会想看看How JavaScript closures are garbage collected, garbage collection with node.js, About closure, LexicalEnvironment and GC and How are closures and scopes represented at run time in JavaScript
当我有一些函数使用其封闭范围内的变量并在此范围(这些范围)之外使用该函数时,这称为闭包。
是否有关于函数必须关闭超过 "how much" 个封闭范围的规范? (或者,换句话说,超过 "how less" 它绝对需要关闭?)
考虑:
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
...?)?
我最感兴趣的是是否有针对这些情况的某种规范,而不是某些特定实现的行为。
嵌套函数的作用域链包含对所有外部函数的激活对象的引用,这些外部函数的执行导致嵌套函数的定义。当外部函数调用返回并继续存在时,这些激活对象将所有值存储在适当的位置,因为它们在作用域链中。
因此,根据定义,闭包捕获范围内的所有变量值。 eval("typeof bigGuy");
在 'function () { /* CONTENTS */ } 中应该证明这一点。
ECMA 标准可能*涵盖了这一点(如果您正在编写 javascript 引擎并且有时间)。一个解决方案可能是在不再需要它们的值时将大型变量设置为 undefined
。
*基于十年前阅读 ECMA 3.61。计算机科学术语 "closure" 没有出现在标准中。闭包的产生必须由 reader 推断为嵌套函数作用域链构建方式的隐含结果——这在标准中。作用域链包括当前正在执行的函数的激活对象,外部函数的激活对象以相反的顺序,然后是全局对象。作用域链不能在用户代码中修改。
I'm mostly interested into whether there is some kind of specification for these cases
ECMAScript specification does not really detail this. It simply says that a function closes over the whole lexical environment 包括所有父作用域中的所有变量,组织在所谓的环境记录中。
然而它并没有指定一个实现应该如何进行垃圾收集——所以引擎确实必须自己优化它们的闭包——它们通常会这样做,当它们可以推断出一些 "closed over" 变量永远不需要时(参考)。具体来说,如果您确实在闭包中的任何地方使用 eval
,他们当然不能这样做,并且必须保留所有内容。
not so much about the behavior of some specific implementation
无论如何,你会想看看How JavaScript closures are garbage collected, garbage collection with node.js, About closure, LexicalEnvironment and GC and How are closures and scopes represented at run time in JavaScript