关于块级作用域,以下代码输出多少,在何时间输出
更多描述
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}
Issue 欢迎在 Gtihub Issue 中回答此问题: Issue 581
Author 回答者: shfshanyue
一秒之后连续输出五个5,以下可输出预期效果
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000 * i);
}
for (var i = 0; i < 5; i++) {
setTimeout(console.log, 1000 * i, i);
}
Author 回答者: aotushi
一秒之后连续输出五个5,以下可输出预期效果
for (let i = 0; i < 5; i++) { setTimeout(() => console.log(i), 1000 * i); } for (var i = 0; i < 5; i++) { setTimeout(console.log, 1000 * i, i); }
为什么setTimeout格式不同,输出的结果也不同.例如:当for循环采用var声明变量,但setTimeout(console.log,1000*i,i)与setTimeout(()=>console.log(i),0)输出的结果不一样.
是因为函数作用域?
Author 回答者: hwb2017
第一种使用var的方式:
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}
第二种使用var的方式:
for (var i = 0; i < 5; i++) {
setTimeout(console.log, 1000 * i, i);
}
var 声明的变量是在函数作用域或者全局作用域的,在第一种方式中,由于setTimeout是异步执行,且它是从闭包中获取 i 变量,由于 i 是在函数/全局作用域中声明的,所以5次循环中 i 不断被赋值,最后 i 的值为5,执行的结果为连续的5个5。
在第二种方式中,通过给setTimeout的回调函数传参的方式,保存了每次循环中 i 的值,因此执行结果符合预期
let声明的变量是在块级作用域(花括号)中的,因此可以认为每次执行循环语句块中的 i 变量是互相独立的,所以执行结果也符合预期