为什么不能在for循环中使用const声明迭代变量
如果我们要写一个for循环,我们可能非常熟练地写出以下代码
for (let i = 0; i < 5; i++) {
console.log(i)
}
我们也很知道,实际上for循环每次循环的时候都会重新初始化一个新的 i。
所以每次的 i 不光值是不同的 它也是不同的变量。
这也是为什么 for let能够解决定时器奇怪输出的原因。
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 0)
}
如果for的每次循环中的 i 是同一个,只是值得变化,那么由于定时器是宏任务,会在同步代码之后执行。
那么它输出得应该是 5 5 5 5 5。
但是现在输出得不同,说明 每次循环中 得 i 是不同的变量,而console.log(i)中的 i 由于函数闭包,可以访问到对应循环中的 i。
实现了符合我们直觉的输出。
好的,扯远了,我现在提出一个问题,既然每次for循环都会去声明一个不同的变量,那么我们平常为什么不用const来声明迭代变量。
for (const i = 0; i < 5; i++) {
console.log(i)
}
因为每次都是声明的不同变量,而不是一个变量,所以每次 i 的改变应该没有什么问题。
而且实际上 在 for of 和 for in循环中,我们可能会写出下面的代码
for (const i of "wuuconix") {
console.log(i)
}
这个代码是能够正常运行的,因为 i 看起来每次都在改变,先是"w",然后是"u"。但是由于每次for循环都会新建一个迭代变量,而 i 在循环体里没有改变,所以这没有任何问题。
但是用在 for 中用const来申明迭代变量会报错。
这究竟是为什么呢?我在循环体里也没有改变 i 呀。
实际上,这个现象可以这个解释,虽然 for会为每次循环新建一个迭代变量,但是 后一个迭代变量的值是通过 上一个迭代变量++后得到的。
即
i n e x t = i n o w + + i_{next} = i_{now}++ inext=inow++
而正是这个 i n o w + + i_{now}++ inow++会导致当前的循环里的 i 的值改变,而因为它是一个const变量,所以就报错了。