JS函数setTimeout底层逻辑全网最清晰的解释

直接的调用者:事件循环(Event Loop)

简单来说,setTimeout中的无参箭头函数是由JavaScript引擎的事件循环机制调用的

下面是详细的执行步骤,说明了这个函数是如何被“调用”的:

  1. 注册回调(你的代码)
    当你调用 setTimeout(() => {...}, 2000) 时,你正在做的是:

    • 调用浏览器(或Node.js)提供的 Web API 中的 setTimeout 函数。
    • 将这个无参箭头函数作为一个回调函数(Callback) 传递给这个API。
    • 同时传递延迟时间 2000ms
  2. 计时器处理(幕后:浏览器/Node.js 内核)

    • setTimeout API 接收到你的请求后,会在它内部创建一个计时器并开始倒计时。
    • 关键点:此时,你的JavaScript主线程不会被阻塞。它会继续执行 setTimeout 之后的代码。setTimeout 函数本身执行完毕并返回。
  3. 计时器到期(幕后)

    • 2000毫秒后,计时器到期。此时,Web API 会将你之前传入的那个回调函数(我们的无参箭头函数)放入一个叫做回调队列(Callback Queue)任务队列(Task Queue) 的数据结构中。
  4. 事件循环接管(JavaScript引擎的核心)

    • 事件循环是一个持续运行的循环,它的职责非常简单:
      • 检查调用栈(Call Stack)是否为空(即主线程上的所有同步代码是否已执行完毕)。
      • 如果调用栈为空,它就去回调队列中检查是否有等待执行的任务。
      • 如果队列中有任务,事件循环就将队列中的第一个任务移出队列,并将其推入调用栈中执行。
  5. 函数执行

    • 一旦回调函数被事件循环推入调用栈,它就会被立即执行。这时,箭头函数内的代码(const success = true; ... resolve(...);)才开始运行。

类比帮助你理解

想象一下你去餐厅吃饭:

  • 你(你的代码):对服务员(Web API)说:“(回调函数)”一份牛排,**(延迟时间)**20分钟后上来。”
  • 服务员(Web API):记下你的订单,后厨开始制作。服务员然后就可以离开去服务其他客人了(不会阻塞)。
  • 后厨(浏览器内核):在20分钟(2000ms)后做好了牛排,把它放在出餐口(回调队列)
  • 传菜员(事件循环):一直在检查出餐口。他看到调用栈(餐桌)是空的(客人吃完了前菜),并且出餐口有做好的牛排(回调队列有任务)。于是他把牛排从出餐口拿到餐桌(调用栈)上。
  • 你吃牛排(函数执行):牛排到了餐桌上,你开始吃它(回调函数被执行)。

在这个过程中,并不是服务员在20分钟后亲手喂你吃牛排,而是整个餐厅的系统协作的结果。同样,在你的代码中,并不是 setTimeout 函数在2000ms后调用了你的箭头函数,而是JavaScript运行时环境通过事件循环回调队列的机制来调度执行的。

总结

步骤执行者操作
1. 注册你的代码调用 setTimeout,传入回调和延迟时间。
2. 计时Web API开始计时,不阻塞主线程。
3. 入队Web API计时结束,将回调函数放入回调队列
4. 调度事件循环检查到调用栈为空,从队列中取出回调函数。
5. 执行JavaScript引擎将回调函数推入调用栈,函数最终被执行

所以,最终的答案是:setTimeout中的无参箭头函数是由JavaScript引擎的事件循环机制,在适当的时机从回调队列中取出并推入调用栈调用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值