极客时间返利平台,你可以在上边通过山月的链接购买课程,并添加我的微信 (shanyue94) 领取返现。
山月训练营之面试直通车 服务上线了,从准备简历、八股文准备、项目经历准备、面试、面经、面经解答、主观问题答复、谈薪再到入职的一条龙服务。

# 关于块级作用域,以下代码输出多少,在何时间输出

更多描述

for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 1000);
}

Issue

欢迎在 Gtihub Issue 中回答此问题: Issue 581 (opens new window)

一秒之后连续输出五个 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 (opens new window)

一秒之后连续输出五个 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 (opens new window)

第一种使用 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 变量是互相独立的,所以执行结果也符合预期

Last Updated: 11/27/2021, 6:11:48 PM