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

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

查看所有标签

猜你喜欢:

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

Is Parallel Programming Hard, And, If So, What Can You Do About

Is Parallel Programming Hard, And, If So, What Can You Do About

Paul E. McKenney

The purpose of this book is to help you understand how to program shared-memory parallel machines without risking your sanity.1 By describing the algorithms and designs that have worked well in the pa......一起来看看 《Is Parallel Programming Hard, And, If So, What Can You Do About 》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

随机密码生成器
随机密码生成器

多种字符组合密码

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具