var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
请问为什么a[6]()会等与10呢?
不应该是在遍历的时候就已经把值给a了吗?
像是这样:
a[0]=function(){
console.log(0);
}
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
请问为什么a[6]()会等与10呢?
不应该是在遍历的时候就已经把值给a了吗?
像是这样:
a[0]=function(){
console.log(0);
}
你可以这么理解:
因为i是在a[i]函数外定义的,所以函数内获取的值是i最终的值。
就好比,你i=1,i=2,...,i=10,虽然你操作了这么多次,最后一次是10.
这涉及到一些闭包的知识。
如果你想要得到,1,2,3,...,10这样的结果,可以修改为这样:
var a = [];
for (var i = 0; i < 10; i++) {
(function(i){
a[i] = function () {
console.log(i);
};
})(i);
}
a[6](); // 6
循环的过程并未执行console.log(i)这个方法,只是把这个方法放到了数组里面,循环结束时i仍然是个变量,但被赋值为10。i等于10的时候并未执行循环,所以不要理解为i应该等于9。此时执行a6了。6指的是数组里的第六个元素,而i已经说过是10了,所以就输出10了。
如果怕复杂就不要把变量提升和闭包弄进来,只是单纯看循环比较好理解一点。
整个作用域中只有一个i,因此i停留在最后一个值10
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
ES6中更加符合你直觉的定义方式为let
(块级作用域)而非var
(函数作用域)
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
所有闭包中的i
都指向一个东西,所以for
循环修改i
之后,闭包中的i
也跟着改。
es5的折衷办法就是bind
掉闭包中的i
,因为i
是原生类型,所以会传值。这种方法也不用什么es6,也不用构建更高阶的函数。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = (function (i) {
console.log(i);
}).bind(null, i);
}
a[6](); // 6
因为函数执行的是
console.log(i)
但是函数中没有定义var i
, 往作用域链外层(上层)寻找var i
;
得到for
循环里面的定义var i
,你执行函数的时候,for
循环已经完成,i
是等于10的,所以结果是10;
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.7k 阅读✓ 已解决
3 回答2.3k 阅读✓ 已解决
3 回答2.1k 阅读✓ 已解决
这个还是闭包的问题嘛,function这个函数只是定义而已,没有运行,运行的时候才回去找i的值。