javascript - 阮一峰大大的ES6入门中的一段代码
阿神
阿神 2017-04-11 09:12:04
[JavaScript讨论组]
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);
}
阿神
阿神

闭关修行中......

全部回复(9)
PHP中文网

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

var i;
a[6]()执行 console.log(i); // 此时i=10;
阿神

个人认为要根据作用域来查找定义的变量,函数内部没有定义,就要往他的上级作用域查找,而for循环是瞬间完成的(你就把循环的速度想的极快吧,反正要比调用的函数快),所以答案是10;

怪我咯

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

阿神

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

迷茫

你可以这么理解:
因为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
PHP中文网

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号