前序

作为一个有理想有抱负的前端攻城狮,想要走向人生巅峰,我们必须将我们使用的功法练到天人合一的地步。我在们日常工作中,使用最多的语言就是JavaScript了,为了写出完美的、能装逼的代码,我们必须对JavaScript有一个非常透彻的理解,也只有这样我们才能随心所欲的去编写的代码。好了,废话不多说,接下来我们就来一起来了解一下,在JS中代码的执行机制到底是怎样的呢?

执行机制中的关键词

1.call-stack 调用堆栈

调用堆栈简单来说就是当前文件执行上下文中的表达式以及被调用的函数所构成的(未被调用的函数不存在调用堆栈中)

英文好的同学可以去WIKI百科查看详细讲解:

https://www.en.wikipedia.org/wiki/Call_stack#FRAME-POINTER

2.macro-task 宏任务

宏任务是JS中的异步执行任务,在执行call-stack时,JS 引擎会将所有宏任务放入宏任务队列中;下面是JS中的宏任务:

  • setTimeout
  • setInterval
  • setImmediate
  • requestAnimationFrame

3.micro-task 微任务

微任务也是JS中的异步执行任务,在执行call-stack时,JS 引擎会将所有微任务放入微任务队列中;下面是JS中的微任务:

  • process.nextTick
  • MutationObserver
  • Promise.then
  • Promise.catch
  • Promise.finnaly

下图是JS的执行机制简图

通过上图,我们对JS的执行机制应该有了粗略的了解,下面我们通过代码的方式来梳理一下,JS的具体执行流程。

// 1.控制台第一步打印下面的console

console.log("Global context");

function fn(){
console.log("fn start"); // 3.当执行这个setTiemout时,这里的函数将被放入
// 到全局的macro-task(宏任务)队列中 setTimeout(function(){ // 当 micro-task (微任务)队列中的函数执行完毕后就会执行第
// 一个被添加到 macro-task 队列中的函数
// 11. 也就是当前的匿名函数
console.log("c"); },0) // 4.JS执行到这里时会把resolve代表的函数放入到
// micro-task (微任务)队列中 new Promise(function(resolve){ // 当call-stack (调用堆栈)执行完毕后就会执行第一个被添加
// 到micro-task 队列中的函数
// 9. 也就是执行resolve代表的函数
resolve('d'); }).then(function(s){
console.log(s);
}) // 5.接着执行下面这行代码
console.log("fn end");
} //2.接着执行fn函数
fn();
// 6.接着执行setTimeout函数
// 当执行这个setTiemout时,这里的函数将被放入
// 到macro-task(宏任务)队列中 setTimeout(function(){ // 12.这里是第二个被添加到 macro-task 队列中的
// 的函数,所以当第一个 macro-task 任务执行完后就会执行这个
// 这个函数,到此为止,所有的 call-stack (调用堆栈)、micro-task
// (微任务)队列、 macro-task (宏任务)队列里的函数全部执行完
// 了,整个 JS 文件里的代码也执行完毕 console.log('macro task 2');
},0); // 7.接着执行Promise函数
// JS执行到这里时会把resolve代表的函数放入到
// micro-task (微任务)队列中 new Promise(function(resolve){
resolve();
}).then(function(){ // 10.这里是第二个被添加到 macro-task 队列中的
// 的函数,所以当第一个 macro-task 任务执行完后就会执行这个
// 这个函数,这个又是最后一个 micro-task 任务,当它也执行完
// 成的时候,JS 就会去执行在 macro-task 任务队列中的函数
console.log('h');
}) // 8.最后执行下面的console console.log('f');

上面代码的标注顺序就是代码在JS中的执行顺序,可能有的朋友会觉得有一点抽象;没关系,下面我们通过对边代码和执行队列图来看看上面代码的JS执行过程

简要概况一下JS的执行过程

在执行当前的 JS 文件时,浏览器会先把全局执行上下文中的表达式、和被调用的函数执行完成,接着再执行放入 微任务队列中的函数,最后执行放入宏任务队列的函数。

代码执行步骤详细描述

  1. 执行这一步打印 Global context;
  2. 执行 fn 方法,首先打印 ‘fn start’
  3. 接着把setTiemout 里的匿名函数放入到宏任务队列中,
  4. 接着执行Promise 并把resolve代表的函数放入微任务队列中,最后打印 ‘fn end’
  5. 接着执行全局中的setTimeout 并把里面的匿名函数放入宏任务队列中
  6. 接着执行全局中的 Promise 并把resolve 代表的函数放入微任务队列中
  7. 接着打印 ‘f’,这个时候 call-stack (调用堆栈)中的代码已经执行完毕,就会去执行第一个放入微任务队列中的函数,及在第4步中的放入的微任务,打印 ‘d’,接着执行第二个放入微任务队列中的函数,及在第6步中放入到微任务队列中的函数,打印 ‘h’
  8. 这个时候微任务队列中的任务已经全部执行完成,接着就会执行宏任务队列中的函数,即fn函数里的setTiemout中的匿名函数,打印 'c’,并把 Promise中的的a所代表的的函数放入微任务队列中。这是微任务队列中就有函数了,这是应该去执行微任务队列中的函数,所以这时就会打印 ‘hello world’,
  9. 这时候微任务队列也为空了,就会去执行宏任务队列中的函数,这时候全局的setTiemout的匿名函数就执行了,打印 ‘macro task 2’,并把函数中的 Promise 中的 a 所代表的函数放入微任务队列中,这是微任务队列也就有了可执行函数,所以现在就会执行微任务队列中的函数,打印 'hello girl’

因为讲的非常详细,所以可能显得啰嗦了,希望大家别介意。由于本人水平有限,如有不当之处还望斧正,以免误人子弟。

深入浅出的JS执行机制(图文教程)的更多相关文章

  1. JS学习笔记:(三)JS执行机制

    首先我们先明确一点:JavaScript是一门单线程语言.单线程也就是说同一时间只能执行一个任务,所有的任务都必须排队顺序执行.那么如果一个任务耗时很长,阻塞了其它任务的执行,就会给用户造成不友好的体 ...

  2. 浅谈js执行机制

    关于js执行机制,老早之前就一直想写篇文章做个总结,因为和js执行顺序的面试题碰到的特别多,每次碰到总是会去网上查,没有系统地总结,搞得每次碰到都是似懂非懂的感觉,这篇文章就系统的总结一下js执行机制 ...

  3. 从一道看似简单的面试题重新理解JS执行机制与定时器

     壹 ❀ 引 最近在看前端进阶的系列专栏,碰巧看到了几篇关于JS事件执行机制的面试文章,因为我在之前一篇 JS执行机制详解,定时器时间间隔的真正含义 博文中也有记录JS执行机制,所以正好用于作为测试自 ...

  4. JS执行机制详解,定时器时间间隔的真正含义

     壹 ❀ 引 通过结果倒推过程是我们常用的思考模式,我在上一篇学习promise笔记中,有少量关于promise执行顺序的例子,通过倒推,我成功让自己对于js执行机制的理解一塌糊涂,js事件机制,事件 ...

  5. js执行机制

    js是单线程的,为什么可以执行异步操作呢? 这归结与浏览器(js的宿主环境)通过某种方式使得js具备了异步的属性. 区分进程和线程: 进程:正在运行中的应用程序.每个进程都自己独立的内存空间.例如:打 ...

  6. 浏览器中js执行机制学习笔记

    浏览器中js执行机制学习笔记 RiverSouthMan关注 0.0772019.05.15 20:56:37字数 872阅读 291 同步任务 当一个脚本第一次执行的时候,js引擎会解析这段代码,并 ...

  7. JS 执行机制笔记

        js同步和异步同步 前一个任务结束以后再执行下面一个任务,程序的执行顺序与任务的排列顺序是一致的 同步任务都在主线程上执行,形成一个执行线 异步 前一个任务没结束之前程序还可以执行别的任务 j ...

  8. 摘录和再编:彻底弄懂JS执行机制

    网文: https://juejin.im/post/59e85eebf265da430d571f89 并发模型和事件循环:https://developer.mozilla.org/zh-CN/do ...

  9. JS执行机制--事件循环--笔记

    JS的解析是由浏览器中的JS解析引擎完成的.JS是单线程运行,也就是说,在同一个时间内只能做一件事,所有的任务都需要排队,前一个任务结束,后一个任务才能开始.但是又存在某些任务比较耗时,如IO读写等, ...

随机推荐

  1. 十三:SpringBoot-基于Yml配置方式,实现文件上传逻辑

    SpringBoot-基于Yml配置方式,实现文件上传逻辑 1.文件上传 2.搭建文件上传界面 2.1 引入页面模板Jar包 2.2 编写简单的上传页面 2.3 配置页面入口 3.SpringBoot ...

  2. Ajax原理,技术封装与完整示例代码

    在做项目和学习的时候,经常用到Ajax的相关技术,但是这方面的技术总是运用的不是十分好,就寻找相关博客来学习加深Ajax技术相关. 一.Ajax简介 二.同步.异步传输区别 2.1 异步传输 2.2 ...

  3. python2.7.5 +eric4.4.2+PyQt4-4.10.3

    1.安装python  双击运行就可以了 当安装好了Pyhon,记得要配置环境变量,把C:\Python27添加到PATH中 2.安装pyqt默认安装就可以 3.把eric4.4.2拷贝到C:\目录下 ...

  4. 入坑wsl

    用了一个月的mac os, 又回归windows了, mac确实好看, 终端配合iterm2也很舒服, 奈何终究我们不合适...生态毕竟没有windows那么丰富; 切回windows最无法忍受的就是 ...

  5. 2018 ACM-ICPC 焦作区域赛 E Resistors in Parallel

    Resistors in Parallel Gym - 102028E 吐槽一下,网上搜索的题解一上来都是找规律,对于我这种对数论不敏感的人来说,看这种题解太难受了,找规律不失为一种好做法,但是题解仅 ...

  6. 组合数取模及Lucas定理

    引入: 组合数C(m,n)表示在m个不同的元素中取出n个元素(不要求有序),产生的方案数.定义式:C(m,n)=m!/(n!*(m-n)!)(并不会使用LaTex QAQ). 根据题目中对组合数的需要 ...

  7. Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)

    题目链接:https://codeforces.com/contest/1362/problem/B 题意 有一个大小及元素值均不超过 $1024$ 的正整数集合,求最小正整数 $k$,使得集合中的每 ...

  8. linux命令行创建快捷方式

    ln -s 源文件 目标目录 https://blog.csdn.net/ljw_jiawei/article/details/91044595

  9. VS Code 配置 Java IDE

    背景 维护的项目在一个内网环境,只能通过跳转机的FTP上传文件.项目是Java spring boot开发,之前的维护人员使用sts(https://spring.io/tools),使用起来体验极差 ...

  10. 洛谷 P1629 邮递员送信-反向建边

    洛谷 P1629 邮递员送信 题目描述: 有一个邮递员要送东西,邮局在节点 11.他总共要送 n-1n−1 样东西,其目的地分别是节点 22 到节点 nn.由于这个城市的交通比较繁忙,因此所有的道路都 ...