美文网首页
JavaScript 运行机制

JavaScript 运行机制

作者: scrollHeart | 来源:发表于2023-07-29 02:39 被阅读0次

JavaScript作为浏览器脚本语言,主要用途是与用户互动,以及操作DOM

JavaScript语言特点:

单线程, 同一个时间只能做一件事。所有任务需要排队,形成"任务队列"。

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。

所有任务可以分成:

  • 同步任务(synchronous)

    在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

  • 异步任务(asynchronous)

    不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行

    • 宏任务(macrotask)

      宿主环境(浏览器/node)发起的任务,每次执行栈执行的代码

      包含生成dom对象、解析HTML、执行主线程js代码、更改当前URL还有其他的一些事件如页面加载、输入、网络事件和定时器事件

      常见API:(setTimeout, setInterval, setImmediate, requestAnimationFrame, I/O, UI rendering)

    • 微任务(microtask)

      由 javaScript 语言标准提供的,由js引擎发起的任务,当前task执行结束后立即执行的任务

      完成一些更新应用程序状态的较小任务,如处理promise的回调和DOM的修改,这些任务在浏览器重渲染前执行。Microtask应该以异步的方式尽快执行,其开销比执行一个新的macrotask要小。Microtasks使得我们可以在UI重渲染之前执行某些任务,从而避免了不必要的UI渲染

      常见API:(Process.nextTick, Promise.then catch finally, Object.observe, MutationObserve)

js的运行机制

(1)所有同步任务都在主线程上执行,形成一个执行栈。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里
  • 当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完

(4)主线程不断重复上面的第三步。

只要主线程空了,就会去读取"任务队列",这个过程会不断重复,这就是JavaScript的运行机制


Event Loop(事件循环),主线程从"任务队列"中读取事件,这个过程是循环不断的。

主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数

回调函数(callback),会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

由于存在"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

setTimeout[1]

 setTimeout(function(){
     console.log('定时器开始啦')
 },3000);
 
 new Promise(function(resolve){
     console.log('马上执行for循环啦');
     for(var i = 0; i < 10000; i++){
         i == 99 && resolve();
     }
 }).then(function(){
     console.log('执行then函数啦')
 });
 
 console.log('代码执行结束');

首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里

遇到 new Promise直接执行,打印"马上执行for循环啦"

遇到then方法,是微任务,将其放到微任务的【队列里】

打印 "代码执行结束"

本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"执行then函数啦"

到此,本轮的event loop 全部完成。下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"定时器开始啦"

JavaScript 运行机制详解:再谈Event Loop

HTML系列:macrotask和microtask

深入理解JS引擎的执行机制


  1. 3秒后,setTimeout里的函数被会推入event queue,而event queue(事件队列)里的任务,,只有在主线程空闲时才会执行。主线程执行内容很多,执行时间超过3秒,比如执行了10秒,那么这个函数只能10秒后执行了

相关文章

网友评论

      本文标题:JavaScript 运行机制

      本文链接:https://www.haomeiwen.com/subject/sxcghltx.html