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

0.0772019.05.15 20:56:37字数 872阅读 291

同步任务

当一个脚本第一次执行的时候,js引擎会解析这段代码,并将其中的同步代码按照执行顺序加入执行栈中,然后从头开始执行。如果当前执行的是一个方法,那么js会向执行栈中添加这个方法的执行环境,然后进入这个执行环境继续执行其中的代码。当这个执行环境中的代码 执行完毕并返回结果后,js会退出这个执行环境并把这个执行环境销毁,回到上一个方法的执行环境。这个过程反复进行,直到执行栈中的代码全部执行完毕。

 
call stack

这个同步代码的执行过程可以是无限进行下去的,除非发生了栈溢出,即超过了所能使用内存的最大值。

异步任务

js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...如此反复

 
image.png

事件队列

我们先看两个实验

// 实验一
console.log('进入页面') setTimeout(() => {
console.log('setTimeout1')
}, 0)
new Promise((resolve) => {
console.log('promise')
setTimeout(() => {
console.log('setTimeout2')
resolve()
}, 0)
}).then(() => {
console.log('then')
})
console.log('代码执行结束') /* 打印结果
进入页面
promise
代码执行结束
setTimeout1
setTimeout2
then
*/

  

// 实验二
console.log('进入页面') setTimeout(() => {
console.log('setTimeout1')
}, 0)
new Promise((resolve) => {
console.log('promise')
resolve()
}).then(() => {
console.log('then')
})
console.log('代码执行结束') /*打印结果
进入页面
promise
代码执行结束
then
setTimeout1
*/

  

上面的两个demo中,demo2里在Promise里使用了setTimeout包了一层。造成then方法中的回调函数执行顺序稍有不同。一个在setTimeout之后,一个在setTimeou之前。为什么会造成这样的结果?

因为事件分为 macro-taskmicro-task。不同的事件会进入不同的队列。
也就是说事件队列对应的也有两个,macro queue和 micro queue

  • macro-task(宏任务):包括整体代码script,setTimeout,setInterval
  • micro-task(微任务):Promise,process.nextTick

上文中提到当主线程闲置后,会去事件队列中查找执行回调函数,这个是有一个先后策略的,先micro queuemacro queue。而这里的promise中只有在执行了resolve()后才会向micro queue中push在then方法里写的回调函数。这也是上边两个实验中console.log('then')执行顺序不同的原因,下面是详细的执行顺序:

实验1:
// 主线程开始执行同步代码
进入页面
//遇到setTimeout1异步挂起,接着执行同步代码
promise
//遇到setTimeout2异步挂起,接着执行同步代码
代码执行结束
// 同步代码执行完毕,主线程闲置,检查micro queue为空,检查macro queue 有两个回调函数
setTimeout1
setTimeout2
//执行了resolve(),向micro queue中push回调函数
//同步代码执行完毕,主线程闲置检查micro queue,执行里边的回调函数
then

  

实验2:
// 主线程开始执行同步代码
进入页面
//遇到setTimeout1异步挂起,接着执行同步代码
promise
//执行了resolve(),向micro queue中push回调函数
代码执行结束
// 同步代码执行完毕,主线程闲置,检查micro queue发现有回调函数执行
then
// 同步代码执行完毕, 主线程闲置, 检查micro queue为空,检查macro queue发现有回调函数并执行
setTimeout1

  

总结

不同类型的任务会进入对应的Event Queue,比如setTimeout和setInterval会进入相同的Event Queue。

事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

 

浏览器中js执行机制学习笔记的更多相关文章

  1. js执行顺序——学习笔记

    我们知道有个全局的 window对象,js的一切皆window上的属性和方法.window上有个window.document属性,记录了整个html的dom树,document是顶层. body 和 ...

  2. JS 执行机制笔记

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

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

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

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

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

  5. Underscore.js 源码学习笔记(下)

    上接 Underscore.js 源码学习笔记(上) === 756 行开始 函数部分. var executeBound = function(sourceFunc, boundFunc, cont ...

  6. Underscore.js 源码学习笔记(上)

    版本 Underscore.js 1.9.1 一共 1693 行.注释我就删了,太长了… 整体是一个 (function() {...}());  这样的东西,我们应该知道这是一个 IIFE(立即执行 ...

  7. JUC.Lock(锁机制)学习笔记[附详细源码解析]

    锁机制学习笔记 目录: CAS的意义 锁的一些基本原理 ReentrantLock的相关代码结构 两个重要的状态 I.AQS的state(int类型,32位) II.Node的waitStatus 获 ...

  8. js执行机制

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

  9. 纯JS实现KeyboardNav(学习笔记)二

    纯JS实现KeyboardNav(学习笔记)二 这篇博客只是自己的学习笔记,供日后复习所用,没有经过精心排版,也没有按逻辑编写 这篇主要是添加css,优化js编写逻辑和代码排版 GitHub项目源码 ...

随机推荐

  1. LTC

    LTC 即 L2C,Leads To Cash,从线索到现金的企业运营管理思想,是以企业的营销和研发两大运营核心为主线,贯穿企业运营全部流程,深度融合了移动互联.SaaS技术.大数据与企业运营智慧,旨 ...

  2. openlayers轨迹匀速播放

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. ASP.NET Identity系列教程-2【Identity入门】

    https://www.cnblogs.com/r01cn/p/5177708.html13 Identity入门 Identity is a new API from Microsoft to ma ...

  4. Selenium实战(三)——滑动解锁+窗口截图

    一.简单滑块的实例 当单机滑块时,改变的只是CSS样式,HTML代码如下: <div class="slide-to-unlock-progress" style=" ...

  5. TP框架中生成带背景带文字的二维码

    首先下载一个phpqrcode的包放到/vendor目录下 链接:https://pan.baidu.com/s/18jV9DypYB_PHDhD6C0iedQ 提取码:qxuo 如果只是单纯生成二维 ...

  6. .NetCore学习笔记:二、基于Dapper的泛型Repository

    为减少代码量,这里实现一个基于Dapper的泛型Repository. 这里需要引用Dapper.dll和Dapper.Contrib.dll. 接口定义: /// <summary> / ...

  7. CentOS 7在执行yum操作时 报错

    CentOS 7在执行yum操作时, 报错:Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch ...

  8. 搜索字母a或A

    Amy觉得英语课实在是无聊至极,他不喜欢听老师讲课. 但是闲着也是闲着,不如做点什么吧?于是他开始数英语书里的字母a和A共出现了多少次. 费了九牛二虎之力终于数完了. 作为一名软件工程专业大学生,他觉 ...

  9. 数据预处理 | python 第三方库 imblearn 处理样本分布不均衡问题

    说明:目前 只记录了 过采样 和 欠采样 的代码部分 1 样本分布不均衡描述: 主要出现在与分类相关的建模问题上,不均衡指的是不同类别的样本量差异非常大. 样本量差距过大会影响到建模结果 2 出现的场 ...

  10. Ionic 使用 NFC

    Ionic 使用 NFC 哎哟喂,因为项目需要使用 Ionic 调用手机 NFC 功能,踩了好多坑,真的是,不过终于不负众望拿到了id.现在就记录一下我的步骤和踩过的坑! 步骤 我装的Ionic可能是 ...