6个6
let i
for(i=0;i<6;i++){
setTimeout(console.log(i),1000)
}
复制代码
这段代码最后会打印出6个6.
i=0: setTimeout(console.log(i),1000),1s后,打印i。有人说,现在i=0啊,为什么不是打印0?因为现在 console.log 这个函数还没有执行,只是定义。没执行的时候,js不会去管里边的内容。
i=1:setTimeout(console.log(i),1000),1s后,还是打印i,而不是1。
一直到 i=5 。然后 i=6 ,跳出循环。for 循环结束了,看看这时到没到1s,如果没到,那就不会去打印。到了1s了,而且现在还不忙,那就去执行函数。
如果后续函数用时很长,那就会在后续函数执行完后再去执行
setTimeout,即setTimeout(fn(),1000)表示1000ms后尽快执行,也就说他只限制了1000ms内不可以执行。
执行的函数是:console.log(i),执行时查看i是几。现在i=6,那就打印6。
后续还有五个函数,console.log(i),i还是6,那就一直打印6.
所以最后的结果就是,打印6个6。
总结:函数在调用的时候才会执行,执行时才会看变量值。
怎么打印0,1,2,3,4,5?
之所以会打印出6个6 ,是因为函数没执行的时候,不会去看里边的值。i 从0到1,0这个值就没了,以此类推,中间的值都没了。
那我们把中间的值保存下来,打印这个保存下来的值不就好了。
let i
for(i=0;i<6;i++){
let j=i
setTimeout(console.log(j),1000)
}
复制代码
i=0: let j=0 ,setTimeout(console.log(j),1000) 1s后,打印j
i=1: let j=1 ,setTimeout(console.log(j),1000) 1s后,打印j
有人说,i=1的时候,j不是变成1了吗,那第一个打印j,打印出来的不就是新的值了吗?
注意,let 是有作用域的,它的作用域是从 { 开始,到 } 结束。也就是说,每次循环,都是一个新的作用域,在每个新的作用域里,j 其实是不同的,互不干扰的。
在 i=0 时,第一个作用域里,j=0 ,那就一直是0。
在 i=1 时,又是一个新的作用域了,在这个新的作用域里,j=1 ,那就一直是1。
其实本质就是 j1,j2,j3 ,是不同的。
所以最后会打印出0,1,2,3,4,5
语法糖
因为其实第二种才是正常的可以理解的结果,所以js直接给了一个语法糖,你不用自己写 let j=i 这句话了,在for循环的 i 前边加一个 let ,就会有同样的效果。
for(let i=0;i<6;i++){
setTimeout(console.log(i),1000)
}
复制代码
结果:打印0,1,2,3,4,5
加一个let ,就会在每次进入循环后,自动为我们创建一个隐形的i',就像j一样,打印的其实是这个i',它会保存下中间的值
立即执行函数
除了用 let 保存中间值外,还有第二种方法,就是立即执行函数。

var 没有作用域。
每次循环,马上执行一个匿名函数,把每次的 i 作为实参,传给它的形参。因为这个匿名函数执行了,所以它里边的 j(j叫i也可以,最前面的括号是形参,最后面的是实参) 就确定了值,就是每次的0,1,2,3,4,5。所以 for 循环结束以后,就会打印出已经定好的0,1,2,3,4,5




















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)