《JS 函数的执行时机》

调用时机 一个函数调用时机不同 他的结果就不同

问题:解释如下代码为什么是6个6

let i=0
for(i=0;i<6;i++){
  setTimeout(()=>{
    console.log(i)  
  },0)
}
问打印出多少?  
6个6

原因:

setTimeout

JavaScript提供定时执行代码的功能,叫做定时器(timer),主要由setTimeout()和setInterval()这两个函数来完成。它们向任务队列添加定时任务。

setTimeout 允许我们将函数推迟到一段时间间隔之后再进行执行,它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器。

let timerId = setTimeout(func|code, [delay], [arg1], [arg2], ...)

func|code是将要推迟执行的函数名或者一段代码

delay是推迟执行的毫秒数

arg1是推迟执行毫秒数之后回调函数执行时,作为回调函数的参数。

返回值timeoutID是一个正整数,表示定时器的编号。这个值可以传递给clearTimeout()来取消该定时器。

在代码中看起来代码的顺序应该好像是从上往下依次执行,但其实不是的。

js执行过程中,当同步和异步代码同时存在时,异步代码会在同步代码全部执行完成后再调用。而setTimeout就是异步代码(就算延迟为零也是异步),它会在代码最后执行,因此执行顺序为先进行for循环。最后才执行setTimeout这时候的i已经经过自增变成了`6,所以最后输出的结果为6个6。

另外值得注意的是setTimeout存在优先级的问题,setTimeout会在指定时间后触发。如果同步代码执行时间大于setTimeout设定时间,那么它将在其他代码执行完成后立即执行。

那么如何实现能让它打出我们想要的 0,1,2,3,4,5,呢?

利用let形成块级作用域

for(let i=0;i<6;i++){
  setTimeout(()=>{
    console.log(i)  
  },0)
}

其他方法:参考来自知乎
一、建立闭包

for (var i = 0; i < 6; i++) {
    (function(index) {
        setTimeout(function() {console.log(index)}, i * 1)
    })(i)
}

因为 Javascript 只有两种作用域,一是全局作用域,二是函数作用域,它是没有块级作用域的

所以闭包的出现就相当于利用一个匿名函数的壳模拟出一个块级作用域

上述代码块往匿名函数内部传的参数将会被拷贝一份,也就是说循环没执行一次就拷贝变量 i 的值到匿名函数内部

 for (let i = 0; i< 6; i++){
      setTimeout((()=>console.log(i))(),0);
    }

知乎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值