更多文章可以看看我的博客:https://icheng.github.io/
题目
for循环中,使用 var 或 let 声明 i 变量,会得到不同的结果
var arr = [];
for (var i = 0; i < 2; i++) {arr[i] = function () {console.log(i);}
}
arr[0]();
arr[1]();
输出:
2
2
var arr = [];
for (let i = 0; i < 2; i++) {arr[i] = function () {console.log(i);}
}
arr[0]();
arr[1]();
输出:
0
1
这是为什么?
解析
首先我们都知道 js 的全局作用域、局部作用域
全局作用域
var 声明在函数体外,属于全局作用域
即意味着:
全局只有一个 i 变量
if (true) {var name = '123';
}
console.log(name); // 输出 '123'
局部作用域
let 声明的变量,属于局部作用域
即意味着:
该变量在 { } 内是有效的
if (true) {let name = '123';
}
console.log(name); // 没有定义
for 循环中 定义 var 发生了什么
每一轮循环,将 function 添加到数组,function 是
function () {console.log(i);
}
因为使用 var 定义 i 变量,所以全局只有一个 i
因此每一轮循环,是全局的这一个 i 在增加
当退出循环后,i = 2
最终执行
arr[0]()
arr[1]()
执行对应的函数
console.log(i);
所以输出:
2
2
所以关键是:
函数是最后执行的,此时函数去找当前的全局变量 i ,是2
for 循环中 定义 let 发生了什么
红宝书上是这样形容的:因为使用 let 定义变量 i,每轮迭代循环时,JS引擎在后台会声明一个新的迭代变量
所以:每个 console.log(i) ,引用的 i 都是不同的变量实例
最终执行函数时,使用自己块级作用域的变量 i
所以输出为:
0
1
所以关键是:
每次循环都会在自己的块级作用域 { } 有变量 i ,最终引用不同的变量实例