比如:
function A() {
var result = [];
for (var i = 0; i < 3; i++)
result.push( function(){ console.log( "item " +i);});
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}//item 3 item 3 item 3为什么调用的是同一个闭包~
function A() {
var result = [];
for (var i = 0; i < 3; i++)
result.push( function(){ console.log( "item " +i);});
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}//item 3 item 3 item 3为什么调用的是同一个闭包~
var result = [];
for (var i = 0; i < 3; i++)
result.push((function(i){ return function(){console.log( "item " +i)};})(i));
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}
仔细看看你push的时候跟我push的时候有什么不一样。
你要让每个添加进数组中的function都单独在一个闭包的作用域里面。每个作用域中都要有一个i变量function A() {
var result = [];
for (var i = 0; i < 3; i++)
(function (i) {
result.push( function(){ console.log( "item " +i);});
})(i);
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}
var result = [];
for (let i = 0; i < 3; i++)
result.push( function(){ console.log( "item " +i);});
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}
不是你想的这样的,运行期的时候方法执行的时候才会去寻找变量的值,所以前面那里push进去的function执行的时候去寻找i的值,这时候i已经是循环结束的结果了。而我上面说的那样方法执行的时候寻找i,i是当时传进去的那个i,可能这样写你会疑惑,换个变量名在理解下吧。
function A() {
var result = [];
for (var i = 0; i < 3; i++)
(function (reali) { // 形参
result.push( function(){ console.log( "item " +reali);}); // 所以这里始终是传进来的实参,所以得到正确的结果。这里运行的时候会去寻找reali变量,reali是外层作用域这个匿名函数传进来的i。
})(i);// 实参
return result;
}
var a = A();
for (var i = 0; i < 3; i++) {
a[i]();
}
但是当这样写的时候
for(i=0;i<3;i++)
{
function test(i)
{console.log(i);}
test(i);
}
这个操作里面 function test里面的i和for里面的i是不在一个存储位置的,test函数声明时定义了形参i循环里的i作为参数传过去之后会在这个函数test所属的空间内重新生成一个i,这个i不会和循环那个i互相影响(除了参数的传递)。这个test所属的这块空间和空间里的变量也可以说就是个闭包。一般都用return把test这个函数运行结果return出去,这样就可以得到这个闭包的运行结果了。
使用闭包的话, 实际上是不同的function的地址引用, 保存不同的数值。还是闭包每次开辟一个新的存储空间?之前的只有一个存储空间。
而定义函数时候会有一个作用域链,作用域链会保存局部变量
因此你可以参考相关资料就可以解释为何会访问最后一个值
(因为定义后,作用域链三层次,最外层全局,第二层包含for循环中的值,第三层才是你定义的函数)
也欢迎去看看我的博客~~