首页 > 阮一峰大大的ES6入门中的一段代码

阮一峰大大的ES6入门中的一段代码

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

这个还是闭包的问题嘛,function这个函数只是定义而已,没有运行,运行的时候才回去找i的值。


循环的过程并未执行console.log(i)这个方法,只是把这个方法放到了数组里面,循环结束时i仍然是个变量,但被赋值为10。i等于10的时候并未执行循环,所以不要理解为i应该等于9。此时执行a6了。6指的是数组里的第六个元素,而i已经说过是10了,所以就输出10了。
如果怕复杂就不要把变量提升和闭包弄进来,只是单纯看循环比较好理解一点。


所有闭包中的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;


你可以这么理解,i变量提升到最上面。

var i;
a[6]()执行 console.log(i); // 此时i=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

楼上正解,的却是每次都赋值了,但是赋值的是个函数吖,这是关键,函数中的变量最后的却是10,所以。。。。

【热门文章】
【热门文章】