例如:
var outter = [];
function fun () {
for (var i = 0; i < 4; i++) {
var x = {};
x.invoke = function () {
console.log(i);
};
outter.push(x);
}
}
fun();
console.log(outter[0].invoke());
console.log(outter[1].invoke());
console.log(outter[2].invoke());
console.log(outter[3].invoke());
结果是:4 4 4 4 。fun()
执行完毕以后局部变量不是释放掉了吗?怎么outter[0].invoke()
还能访问到局部变量i
?
牵扯到js中
函数作用域链
和闭包的问题哦。如果闭包对函数中的一个对象未来有引用的话,这个对象不会被释放哦
经典的闭包问题
http://bonsaiden.github.io/JavaScript-Garden/zh/#function.closures
你的 i 一直都在被使用中,你 fun(); 之后那个 i 就变成 4 了。
然后你之后的每一次 outter[0].invoke() 当然都是 4 了。
然后这个所谓的局部变量就永远不会被回收了,因为你的每个 outter[].invoke() 都要用到这个 i 。
正确的应该是
还有你的代码中 函数里面 为什么写那么多遍 console.log,你的 invoke() 函数不是已经有了 console.log() 的功能了?
直接 outter[1].invoke(); 不就直接输出了?
题外话:正确的使用工具才能事半功倍。
今天刚刚看到JavaScript高级程序设计(第3版)才发现书里面有个例子(7.2.1 闭包与变量)和我这个问题一样。
书中提到:作用域链的配置机制引出了一个副作用,即闭包只能取得包含函数中任何变量的最后一个值。但是可以通过创建另一个匿名函数强制让闭包的行为符合预期。
当
fun()
函数执行完毕后,它的执行环境的作用域链会被销毁,但是它的活动对象仍然会留在内存中,直到匿名函数被销毁后才被销毁。fun
执行后:对于每个
invoke
函数创建时:每个
invoke
执行时,其上下文作用域链: