6 回答

TA贡献1995条经验 获得超2个赞
这个题已经问烂了也回答不知道多少遍了
i是全局变量 函数调用的时候获取i 此时 i已经循环到了10
下面是个简单了例子可以理解为经历了两次循环
var i = 1;
function a1(){ console.log(i) }
var i = 2;
function a2(){ console.log(i) }
a1();//2
a2();//2
解决方法 将i变为局部变量
es6
{
let i = 1;
function a1(){ console.log(i) }
}
{
let i = 2;
function a2(){ console.log(i) }
}
a1();//1
a2();//2
//es6 let局部变量
for(let i=0;i<10;i++) ...
//or
//自执行函数 es5中只有函数内有局部作用域
for (var i = 0; i < 10; i++) {
a[i] = (function(i){
return function () {
console.log(i);
};
})(i)
}

TA贡献1860条经验 获得超9个赞
问题源于对函数作用域(链)的理解不够深,一下是个人的一点见解,望能帮助到您:
var a = [];
for (var i = 0; i < 10; i++) { // 此处变量i为全局变量,属于外层作用域(window)
// 此处声明函数,创建函数的作用域(建立作用域链,函数内部能访问外层作用域中的i变量,但此处只是声明,并不执行)
a[i] = function () {
// 函数内部并未定义i变量,当函数执行时通过声明函数时建立的作用域链向上查找变量i
// 调用a[6]时,for循环已经结束,变量i已经变成10,所以此处打印输出 10
console.log(i);
};
}
a[6](); // 10

TA贡献1875条经验 获得超5个赞
其实 es6 的 let 根本没抓住问题的本质
关键在于 js 作为一个允许副作用的语言,它的 closure 却只支持引用外层作用域的变量,而不支持「引用」外层作用域中变量的值
C++ 就没有这个问题~
#include <functional>
#include <iostream>
using namespace std;
int main() {
function<void()> a[10];
for (int i = 0; i < 10; i++) {
a[i] = [i] () {
cout << i << '\n';
};
}
a[6](); // 6
}
之所以出现这个反直觉的现象,就是因为你那 10 个函数引用的都是同一个 i 变量,而这个变量的值是 for 循环最后一次执行时的值,也就是 10。
添加回答
举报