JavaScript 的运行机制

栏目: JavaScript · 发布时间: 5年前

内容简介:作为一个前端er,最基本的要求也得知道js的运行机制叭。由于js是单线程的,所以js是按顺序执行的。来点复杂的。

作为一个前端er,最基本的要求也得知道js的运行机制叭。由于js是单线程的,所以js是按顺序执行的。

console.log('1')
console.log('2')
输出:1,2。果然是按顺序执行的。本文结束。
复制代码

来点复杂的。

setTimeout(function () {
      console.log('1')
    })
    new Promise((resolve) => {
      console.log('2')
      resolve()
    }).then(() => {
      console.log('3')
    })
    console.log('4')
输出:2,4,3,1。这个是为啥子嘞。
复制代码

从 js 单线程说起

js 是一门单线程的语言,设计之初,是在浏览器中运行的,方便处理 DOM 树的。如果是多线程的话,一个线程删除 DOM ,一个线程修改 DOM ,这样就会出现问题。 HTML5 引入了 web workers ,使 js 能够创建多个线程,是为了防止大量的数据计算阻塞 UI 渲染,但这些线程都是受主线程控制的,所以 js 在本质上还是单线程的。

表面很难的event loop

js 是单线程的,所以一次只能执行一个任务,当一个任务需要很长时间时,主线程一直等待任务的执行完成,在执行下个任务是很浪费资源的。

比如,我们吃泡面时候,先烧水,在等待水烧开的时候,我们可以把泡面打开,作料放好,等水开了,直接泡就好。那个吃干脆面的走开。

所以, js 中任务就被分成两种,一种是同步任务,一种是异步任务。执行步骤如下图所示:

JavaScript 的运行机制

宏任务和微任务

为了更精细的区分任务, js 中可以将异步任务划分为宏任务和微任务。

js 代码在执行时,首先执行 js 同步任务,然后执行所有微任务,再执行所有宏任务,以此循环下去,直到所有任务全部执行完成。

  • 常见的宏任务: setTimeoutsetInterval
  • 常见的微任务: promise.then 。 看下这段代码:
setTimeout(function () {
      console.log('1')
    })
    new Promise((resolve) => {
      console.log('2')
      resolve()
    }).then(() => {
      console.log('3')
    })
    console.log('4')
    
复制代码
  • 首先执行setTimeout,进入任务队列,注册成宏任务。
  • Promise,直接执行,输出:2,然后promise.then,进入任务队列,注册成微任务。
  • 然后遇到console.log('4'),直接输出:4。
  • 同步任务执行完,从任务队列中找出要执行的微任务,输出:3。
  • 然后执行宏任务,输出:1。 下面我们看个更复杂的例子:
console.log('1');
    setTimeout(function () {
      console.log('2');
      new Promise(function (resolve) {
        console.log('3');
        resolve();
      }).then(function () {
        console.log('4')
      })
    })
    new Promise(function (resolve) {
      console.log('5');
      resolve();
    }).then(function () {
      console.log('6')
    })

    setTimeout(function () {
      console.log('7');
      new Promise(function (resolve) {
        console.log('8');
        resolve();
      }).then(function () {
        console.log('9')
      })
    })
    console.log('10')

复制代码
  • 首先输出:1,然后注册宏任务 setTimeout1 。然后输出5,注册微任务 promise1 ,然后注册宏任务 setTimeout2 ,然后输出10。所以第一轮的事件循环,输出了 1 5 10 ,注册了微任务 promise1 ,宏任务 setTimeout1、setTimeout2
  • 然后 promise1 进入主线程,执行微任务 promise1 ,输出: 6
  • 随后宏任务 setTimeout1 进入主线程,执行宏任务 setTimeout1 ,输出: 2 3 ,注册微任务 promise2
  • 注意的地方来了,宏任务 setTimeout1 执行完后,我们发现有微任务 promise2 在任务队列中,所以微任务 promise2 进入主线程,执行微任务 promise2 ,输出: 4
  • 随后宏任务 setTimeout2 进入主线程,输出: 7 8 ,注册微任务 promise3
  • 最后微任务 promise3 进入主线程,输出: 9

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

现代操作系统(第3版)

现代操作系统(第3版)

Andrew S. Tanenbaum / 陈向群、马洪兵 / 机械工业出版社 / 2009-7 / 75.00元

本书是操作系统领域的经典之作,与第2版相比,增加了关于Linux、Windows Vista和Symbian操作系统的详细介绍。书中集中讨论了操作系统的基本原理,包括进程、线程、存储管理、文件系统、输入/输出、死锁等,同时还包含了有关计算机安全、多媒体操作系统、掌上计算机操作系统、微内核、多核处理机上的虚拟机以及操作系统设计等方面的内容。此外,还在第2版的基础上对部分习题进行了增删,更有助于读者学......一起来看看 《现代操作系统(第3版)》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具