前序

作为一个有理想有抱负的前端攻城狮,想要走向人生巅峰,我们必须将我们使用的功法练到天人合一的地步。我在们日常工作中,使用最多的语言就是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. Linux 配置永久辅助IP

    1.什么是辅助IP 辅助IP来源于Linux之中,Linux的系统网卡可以支持多IP的绑定,而辅助IP多用于解耦解决服务之间的兼容性问题,常见的应用场景有: 虚拟IP,高可用飘逸: 永久临时IP解耦使 ...

  2. Think in Java 第四 五 章

    Think in Java 第四章 控制执行流程 测试while public class whileTest { static boolean condition(){ boolean result ...

  3. C - Door Man(欧拉回路_格式控制)

    现在你是一个豪宅的管家,因为你有个粗心的主人,所以需要你来帮忙管理,输入会告诉你现在一共有多少个房间,然后会告诉你从哪个房间出发,你的任务就是从出发的房间通过各个房间之间的通道,来把所有的门都关上,然 ...

  4. 2019CCPC厦门站总结

    这是一篇打铁游记~ $day1$ 坐动车去厦门,三个人买了一堆零食,吃了一路,除了睡觉嘴巴基本就没停过.当然,我们到酒店后也去吃了烧烤,我们虽然是在岛外的厦门北站的下的,还是很幸运的找到一家好吃了,乌 ...

  5. 动态规划TG.lv(1) (洛谷提高历练地)

    动态规划TG.lv(1) P1005 矩阵取数游戏 分析:每行不超过80个数字,直接区间DP即可,\(dp[i][j]\)表示区间\([i,j]\)之间取数可以得到的答案,每次向右或者向左扩展即可.但 ...

  6. 阅读笔记:Very Deep Convolutional Networks for Large-Scale Image Recognition

    摘要: 在这篇论文我们主要研究卷积神级网络的深度对大范围图像识别效果的影响,我们发现增加神经网络层数增加到16-19层时我们的实验结果有很大的提高.这使得我们在2014年的ImageNet Chall ...

  7. POJ - 3693 Maximum repetition substring(重复次数最多的连续重复子串)

    传送门:POJ - 3693   题意:给你一个字符串,求重复次数最多的连续重复子串,如果有一样的,取字典序小的字符串. 题解: 比较容易理解的部分就是枚举长度为L,然后看长度为L的字符串最多连续出现 ...

  8. SP3267 DQUERY - D-query 莫队板子题

    题意可见:https://www.luogu.com.cn/problem/SP3267 可在vj上提交:https://vjudge.net/problem/SPOJ-DQUERY 题意翻译 给出一 ...

  9. 【uva 1471】Defense Lines(算法效率--使用数据结构+部分枚举+类贪心)

    P.S.我完全一个字一个字敲出来的血泪史啊~~所以,没有附代码,也是可以理解的啦.OvO 题意:给一个长度为N(N≤200000)的序列,要删除一个连续子序列,使得剩下的序列中有一个长度最大的连续递增 ...

  10. UVA442 矩阵链乘 Matrix Chain Multiplication

    题意: 这道题也是在不改变原序列每个元素位置的前提下,看每个元素与他身边的两个元素那个先结合能得到最大的能量 题解: 很明显这是一道区间dp的题目,这道题要断环成链,这道题需要考虑在这个区间上某个元素 ...