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

任务队列

大家都知道js最大的特点就是单线程执行,这就是为什么js简单易学的一个重要原因,不需要考虑复杂的同步问题,但是单线程也会有一个问题,所有的任务在执行的过程中都必须等待前一个任务执行完成才能执行,这样就会带来一个效率的问题,为了解决这个问题,js将任务分为两种:同步任务和异步任务,同步任务就是之前说后一个任务必须等待前一个任务执行完成才能执行,是在主线程上执行的,而异步任务不会直接进入主线程执行,而是进入任务队列,只有在任务队列通知异步任务可以执行时,才会被推入主线程执行。让我们来看一个更加直观的流程图:

setTimeout和setInterval

说到异步任务,最常见就是setTimeout和setInterval两兄弟了,setTimeout是延迟一定时间后执行,但是只执行一次,setInterval是每隔一定的时间执行一次,会执行多次,但是有时候我们会发现设置一定的延迟时间后,回调函数的执行时间会比我们设置的时间要晚,这是为什么呢?上面我们说过,在任务执行的时候setTimeout这类异步任务的回调会被放到异步队列中等待执行,当延迟时间结束时,如果主线程的任务已经执行完了,也就是处在空闲状态时,就会将任务队列的回调推到主线程执行,但是当主线程的任务还没有执行完成时,就只能继续等待,来看一个例子:


let before = new Date()
setTimeout(() => {
console.log(new Date() - before)
}, 1000)
for (let i = 0; i < 300000; i++) {
console.log('time delay')
}

从上面的例子就可以看到:当我们执行完setTimeout之后,立刻执行20万次的循环,从执行结果可以看到,setTimeout回调函数中的时间远高于设置1000ms,这就是因为时间到了,但是主线程的任务还没有执行完成导致。这种问题在setInterval设置倒计时的经常遇到,倒计时开始的时候设置的时间是从服务器拿到的系统时间很准确,但是如果后面不定期像服务期请求系统时间进行校准的话,你可能会发现倒计时的偏差越来越来大,这就是主线程执行的时间比设定的延迟时间长导致的。

macrotask和microtask

在js中,异步任务除了有setTimeout这类的异步任务,还有一类就是es6中很常用promise...then这类的异步任务,因此除了同步任务和异步任务,任务还可以更加细分为macrotask(宏任务)和microtask(微任务)
macrotask: 包括setTimeout、setInterval和执行栈
microtask: 包括Promise、process.nextTick
要想理解这两个概念,直接从一道简单的面试题入手,来看一个例子:


setTimeout(function() {
console.log(1)
}, 0);
new Promise(function(resolve, reject) {
console.log(2);
resolve()
}).then(function() {
console.log(3)
});
process.nextTick(function () {
console.log(4)
})
console.log(5)

思考一下上面例子的输出结果,我们来仔细分析一下执行过程:

  • 第一轮:主线程开始执行,遇到setTimeout,将setTimeout的回调函数丢到宏任务队列中,在往下执行new Promise立即执行,输出2,then的回调函数丢到微任务队列中,再继续执行,遇到process.nextTick,同样将回调函数扔到为任务队列,再继续执行,输出5,当所有宏任务执行完成后看有没有可以执行的微任务,发现有then函数和nextTick两个微任务,先执行哪个呢?process.nextTick指定的异步任务总是发生在所有异步任务之前,因此先执行process.nextTick输出4然后执行then函数输出3,第一轮执行结束。
  • 第二轮从宏任务队列开始,发现setTimeout回调,输出1执行完毕,因此结果是25431

最后用一张图来总结一下:

总结

这篇文章简单介绍了js执行机制,希望看了之后,可以对大家认识js的执行机制会有所帮助。
如果有错误或不严谨的地方,欢迎批评指正,如果喜欢,欢迎点赞收藏

来源:https://segmentfault.com/a/1190000017393686

浅谈js执行机制的更多相关文章

  1. 浅谈js运行机制

    前言 因为js的运行机制十分重要,理解起来也十分抽象,仍还是在这里做个记录,加深自己的记忆. 总之,希望本文的内容能够对您的学习或者工作有所帮助.另,如果有任何的错误或者不足请指正! 如何理解js单线 ...

  2. 浅谈JS执行环境及作用域

     今天刚刚开通博客,也是第一次写博文,略感紧张.作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习 ...

  3. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  4. 浅谈JS之AJAX

    0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...

  5. 浅谈JS中的闭包

    浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...

  6. 浅谈 js 语句块与标签

    原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...

  7. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

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

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

  9. 浅谈js拖拽

    本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...

随机推荐

  1. 能量项链(codevs 1154)

    题目描述 Description 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N颗能量珠.能量珠是一颗有头标记与尾标记的珠子,这些标记对应着某个正整数.并且,对于相邻的两颗珠子 ...

  2. Linux下重启就需要重新激活eth0的解决办法(ifup eth0)

    新安装linux系统,网卡不能自动激活去获取ip,每次都需要手工执行以下命令 ifup eth0 后续通过将ONBOOT=yes这句就能开机启动自动激活,就可以解决问题 vim /etc/syscon ...

  3. 如何新建.htaccess文件

    如何新建.htaccess文件 (1)新建文本文档,即txt文件: (2)把重写代码写进去: (3)然后选择[另存为],命名为.htaccess即可.

  4. ZOJ 3717 二分+2-sat判定。

    好久没有2-sat了,此题当复习之用,二分求最大值+2-sat判断可行,此题主要跪于题意:The results should be rounded to three decimal places. ...

  5. hdu - 3836 Equivalent Sets(强连通)

    http://acm.hdu.edu.cn/showproblem.php?pid=3836 判断至少需要加几条边才能使图变成强连通 把图缩点之后统计入度为0的点和出度为0的点,然后两者中的最大值就是 ...

  6. 快速掌握RabbitMQ(二)——四种Exchange介绍及代码演示

    在上一篇的最后,编写了一个C#驱动RabbitMQ的简单栗子,了解了C#驱动RabbitMQ的基本用法.本章介绍RabbitMQ的四种Exchange及各种Exchange的使用场景. 1 direc ...

  7. Centos7安装遇到的问题及详解

    1.虚拟机中选择的是NAT模式,我的笔记本电脑是拨号上网,用桥接模式,找不到网卡,在windows的dos界面用ipconfig查看的结果 PPP适配器 宽带连接:IPv4 地址 . . . . . ...

  8. SolidEdge如何自动标注尺寸

    1 工具-尺寸-关系助手(必须在编辑草图轮廓状态下,如果你的草图不可编辑,则没有这些选项)   2 框选要自动标注尺寸的东西,这些东西立即变为黄色,然后打对勾   3 选择横纵坐标尺寸原点(其实就是为 ...

  9. 【从零学习openCV】IOS7下的openCV开发起步(Xcode5.1.1&amp;openCV2.49)

    前言: 开发IOS7已经有一月的时间了.近期在准备推研的事,有点想往CV方向发展.于是開始自学openCV. 关注CSDN已经非常久了.也从非常多博主那学到了非常多知识,于是我也从这周开启自己的blo ...

  10. 【试水CAS-4.0.3】第06节_CAS服务端配置HTTPS

    完整版见https://jadyer.github.io/2012/05/30/tomcat-https/ /** * @see CAS服务端配置HTTPS * @see -------------- ...