一个你可能觉得很奇怪的现象
var batch = [];
var i = 0;
for(;i < 5; i++){
batch.push(function closureFn(){
console.log(i);
});
}
batch.forEach(function(item){item();console.log("<"+i+">")});
输出
5
<5>
5
<5>
5
<5>
5
<5>
5
<5>
输出的值都是i最后的结果
这个函数做的事情是向push数组中存放元素 这个元素是函数 且函数没有执行
所以输出一下batch得到
[function closureFn(){
console.log(i);
}, function closureFn(){
console.log(i);
}, function closureFn(){
console.log(i);
}, function closureFn(){
console.log(i);
}, function closureFn(){
console.log(i);
}]
对batch的每一项进行遍历
forEach中的item就是
function closureFn(){
console.log(i);
}这个函数
故item() 运行的话就是输出最终的i值
PS batch这个数组中的forEach的回调函数中变量i是全局变量i
或者用这个例子
var batch = [];
var i = 0;
for(;i < 5; i++){
batch.push(function closureFn(){
return i;
});
}
batch.forEach(function(f){console.log(f())});
得到5个5
这也是同样的道理
//使用立即执行函数来解决这个问题
var batch = [];
var i = 0;
for(;i < 5; i++){
batch.push(function closureFn(i){
console.log(i+" .. ");
return i;
}(i));
}
console.log(batch); //[0, 1, 2, 3, 4]
或者这样 加深印象
var batch = [];
var i = 0;
for(;i < 5; i++){
batch.push(function closureFn(index){
return function(){ console.log(i+" "+index)};
}(i));
}
batch.forEach(function(item){item()});
输出结果
5 0
5 1
5 2
5 3
5 4
这里使用了立即执行函数 所以每一次循环参数index得到的都是该轮循环的index
PS index不是i的引用 而是每次循环的时候i将自己的值传给index
closureFn这个函数立即执行 并且返回一个函数 这个返回的函数就是batch中的一个元素
PS 闭包中保存的是外部变量的引用而非值
所以for循环执行完后 i的值就已经是5 forEach每一项 在执行返回函数的时候i就是5
原文地址:http://www.cnblogs.com/cart55free99/p/3805974.html