1.首先看如下代码,运行结果为0,1,2,3,4,5应该毫无疑问,从i=0开始,每次for循环i++,直到i=6不满足条件,退出循环,故只打印0,1,2,3,4,5
//代码一
let i = 0
for(i = 0; i<6; i++){
console.log(i)
}
2.再看如下代码?他的运行结果是什么?
//代码二
let i = 0
for(i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
代码的运行结果如上所示,为什么会打印6个6?而不是0,1,2,3,4,5呢?首先看两个for循环的区别在哪里?代码二比代码一多了一个setTimeout函数,那这样就好理解了,多了一个定时器,每次循环执行到定时器要等一会,要先将当前的事情做完,当前的事情也就是for循环,等到循环结束后,i=6退出for循环,此时开始做setTimeout函数中需要做的事情,也就是打印i,此时i为6,故打印6,那为什么打印六个呢?因为有6个setTimeout函数在等待,每循环一次就有一个setTimeout函数在等待,总共6个,因此打印6个6。不对啊,定时器中设置是0秒钟后执行啊,难道不等于立即执行吗?不等于,这牵扯到js中异步任务,当执行到setTimeout函数的时候,就会将此任务添加到任务队列,只有将手头的for循环做完后,才会执行任务队列中的未完成的事情。如果暂时不能理解任务队列,就先理解为,setTimeout就是让等一会,等0秒也需要等。
3.如何让上面代码二打印 0、1、2、3、4、5
//代码三
//修改声明变量i的地方
for(let i = 0; i<6; i++){
setTimeout(()=>{
console.log(i)
},0)
}
运行结果如上所示,此时即可打印出0,1,2,3,4,5。这是为什么呢?代码三中使用let声明i,此时js会自己在每次for循环之前,用let声明一个变量存储i的值,记为_i,而let声明的_i具有局部作用域,也就是说,每次循环时i的值都会被赋值给_i,会被保存在每次循环的那个局部作用域中,等for循环执行完后,过会执行六个setTimeout时,每个setTimeout打印的都是这个setTimeout所在作用域的_i,也就是0,1,2,3,4,5。而代码二中的i存在在全局作用域中,故每次循环均会改变i的值,因此最终i为6。也可以理解为代码二中只有一个全局的i,每次for循环都会改变其值,而代码三中,在每次for循环中,都定义了一个局部_i,总共六个,这六个_i互不影响。
4.有什么其他方法打印0,,1,2,3,4,5(不使用for,let)
//最简单的如代码一所示
//代码四
//立即执行函数和闭包
for(var i=0;i<6;i++){
!function (i){
setTimeout(()=>{
console.log(i)
},0)
}(i)
}
运行结果如下
立即执行函数就是声明一个匿名函数,马上调用这个匿名函数。 它只有一个作用:创建一个独立的作用域。这个作用域里面的变量,外面访问不到(即避免「变量污染」)。这样每个作用域中就会维护一个i。从而最后打印不同的i。