函数调用的时机不同,运行结果也不同。
为什么如下代码会打印 6 个 6,而不是 0,1,2,3,4,5?
/* 例 1 */
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{ // 延时函数
console.log(i)
},0)
}
setTimeout() 函数是干嘛的?
MDN 给出的描述是:
**setTimeout()**
方法设置一个定时器,该定时器在定时器到期后执行一个函数或指定的一段代码。白话理解:
- 凡是放在这个函数中的东西,都过一会再做,至于过多久,可以通过设定毫秒数来调节。
😉 如果 **setTimeout**
延时设置为 0 呢?
- 如代码例 1 中
**setTimeout**
作为延时函数设置延时为 0 时,意思是尽快执行完 for 循环,然后立马执行setTimeout
打印出i
的值。 - 循环执行完时
i = 6
,由于for
循环了6次,也就是i = 6
之后再去打印 6 次i
,所以打印结果为 6 个 6
如何让例 1中的代码 打印出 0,1,2,3,4,5?
/* 把 let 直接写到 for 循环里 */
for(let i = 0; i<6; i++){
// let i = 隐藏作用域中的i
setTimeout(()=>{
console.log(i)
},0)
} // 打印结果为 0,1,2,3,4,5
在 for循环表达式中使用 let声明表达式变量
**for( let i = 0; i< 6; i++)**
这句话的圆括号之间,有一个隐藏的作用域。**for( let i = 0; i< 6; i++) { 循环体 }**
在每次执行循环体之前,JS 引擎会把**i**
在循环体的上下文中重新声明及初始化一次。- 因为
**let**
有自己的作用域块,所以在 for循环表达式中使用**let**
它的每一个值都会单独存在一个独立的作用域中不会被覆盖掉。- 每次进入
for
循环时都把i
复制一份,就是第一次循环把i
留在这个空间,后面的每一次都这样操作就有 6 个新的i
,再加上本身i = 0
的这个i
,一共就有 7 个i
。 - 这样就是
i
从 0 到 6,每次都把i
打出来,最后就是打出 0~5 ,因为i = 6
时就跳出了循环。参考资料: 方方:我用两个月的时间理解 let
- 每次进入
除了使用 for let 配合,还有什么其他方法可以打印出 0、1、2、3、4、5?如下:
/* 1.闭包 */
let i
for(i = 0; i<6; i++){
!function(j){
setTimeout(()=>{
console.log(j)
},0)
}(i)
} // 打印: [0,1,2,3,4,5]
/* 2.数组的push */
var arr1 = [];
var n = 0;
for(var i = 0; i<6; i++)
{
n += 1;
arr1.push(n-1)
}
console.log(arr1) // 打印: [0,1,2,3,4,5]
/* 3.利用 setTimeout 的第三个参数,将i传进去 */
let i
for(i = 0; i<6; i++){
setTimeout((value)=>{
console.log(value)
},0,i)
} // 打印: [0,1,2,3,4,5]
/* 4.利用 const 关键字 */
let i
for(i=0; i<6; i++){
const x = i
setTimeout(() => {
console.log(x)
})
}