正文
JavaScript
有一个特点,也许会让开发者头痛, 是与循环和作用域相关的.
举个例子:
const operations = []
for (var i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
它基本是循环了5次,将一个函数添加到operations数组里面。这个函数可打印出循环变量索引值
i
.
运行这些函数后
期望的结果应该是:
0
1
2
3
4
但实际发生的是这样的:
5
5
5
5
5
为什么会有这种情况? 因为使用的是
var
.
由于
提升
了
var
变量, 上面的代码等同于
var i;
const operations = []
for (i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
因此,在for-of循环中,
i
依然是可见的, 它等于5,并且每次在函数中涉及到
i
,都将使用这个值。
那么我们应该如何做让其变成我们想的这样呢?
最简单的方案是用
let
声明. 在ES2015中介绍到, 它们有很大的帮助,能避免关于使用
var
声明的一些奇怪问题。
简单的在循环变量时将
var
变成
let
,能够很好的运行:
const operations = []
for (let i = 0; i < 5; i++) {
operations.push(() => {
console.log(i)
})
}
for (const operation of operations) {
operation()
}
这是输出结果:
0
1
2
3
4
这是怎么实现的呢?这是因为每次循环重复的时候,都将重新创造
i
,同时每个函数添加
operations
数组时,能获取它本身的
i
。
记住你不能使用
const
在这种情况下, 因为这会导致
for
在第二次循环时, 尝试赋新值报错。