道歉,如果我的术语稍微偏离......当一个函数包装另一个函数并创建一个闭包时,每次调用外部函数时是否创建了一个闭包的新实例(“内存空间”?)?
从我的代码中我相信答案是肯定的:
(function(){
var ob = {}, names=['one', 'two'], i=0;
var outer = function(val){
ob[names[i++]] = function(){
return val;
};
};
outer(3);
outer(999);
console.log(ob.one());
console.log(ob.two());
})();
鉴于结果是
3
999
而不是
999
999
似乎ob.one
指向ob.two
的另一个闭包实例 - 每个val
都有自己的值。
这比我的术语更令人困惑吗?
答案 0 :(得分:3)
是否为每个嵌套函数创建了一个单独的闭包实例?
是的,这是一个理想的功能
更令人向往的功能是块级范围,javascript没有。实际上,有必要滥用嵌套函数以便在javascript中执行嵌套for
- 循环,否则变量绑定将在您的背后变异(例如,如果您将其交给回调,您自己演示;想象一下你所定义的函数,例如,针对不同元素的onClick处理程序;你想要绑定是不同的。)
当然,如果你不喜欢这个功能,你总是可以使用你在外部范围内定义的变量,比如你也可以。 =)
答案 1 :(得分:0)
如果ob
被调用inner
会更好,但无论如何......
...每次调用外部函数时都会创建一个闭包的新实例(“内存空间”?)?
是和否。分配给外部的函数具有对外部匿名函数的激活/变量对象的闭包。调用外部时,该对象将放置在其作用域链上,并用于标识符解析。这是每次都是相同的对象(ECMA-262没有说明如何做到这一点,但是对于所有意图和目的而言,它是同一个对象)。
分配给ob[names[i++]]
的函数对调用外部并分配函数时创建的激活/变量对象的实例有一个闭包。因此,每次调用外部时,都会创建一个新的激活/变量对象,并且每个 ob [..] 函数都有一个对不同外部激活/变量对象但具有相同的匿名函数激活/变量对象。
我希望这是有道理的。
鉴于结果是
3 999
而不是
999 999
似乎ob.one指向a ob.two的不同闭包实例 - 每个都有自己的val值。
两个函数在其作用域链上具有相同的匿名函数激活/变量对象,因此“共享”对 obj ,名称和 i <的闭包/ em>的。但每个作为其范围链上的外部激活/变量对象的唯一实例,因此 val 将解析为相同的属性名称,但在不同的对象上(即它们不会共享相同的 val 属性)。
可能下面的范围链图是有意义的:
ob.one -> outerA -> anonymous fn -> global
ob.two -> outerB -> anonymous fn -> global
所以 ob.one 和 ob.two 在其作用域链上有一个外部实例,但它们是不同的实例。它们在作用域链上具有相同的匿名函数和全局对象。