浅谈js执行机制
关于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执行机制的更多相关文章
- 浅谈js运行机制
前言 因为js的运行机制十分重要,理解起来也十分抽象,仍还是在这里做个记录,加深自己的记忆. 总之,希望本文的内容能够对您的学习或者工作有所帮助.另,如果有任何的错误或者不足请指正! 如何理解js单线 ...
- 浅谈JS执行环境及作用域
今天刚刚开通博客,也是第一次写博文,略感紧张.作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习 ...
- 浅谈 js 正则字面量 与 new RegExp 执行效率
原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...
- 浅谈JS之AJAX
0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HT ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- 浅谈 js 语句块与标签
原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象 ...
- 浅谈 js eval作用域
原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...
- JS学习笔记:(三)JS执行机制
首先我们先明确一点:JavaScript是一门单线程语言.单线程也就是说同一时间只能执行一个任务,所有的任务都必须排队顺序执行.那么如果一个任务耗时很长,阻塞了其它任务的执行,就会给用户造成不友好的体 ...
- 浅谈js拖拽
本文来自网易云社区 作者:刘凌阳 前言 本文依据半年前本人的分享<浅谈js拖拽>撰写,算是一篇迟到的文章. 基本思路 虽然现在关于拖拽的组件库到处都是,HTML5也把拖放纳入了标准.但考虑 ...
随机推荐
- 【二分+扫描线乱搞】B. Producing Snow
注意二分写法... http://codeforces.com/problemset/problem/923/B #include<cstdio> #include<string.h ...
- spring5响应式编程
1.Spring5新特性 2.响应式编程响应式编程:非阻塞应用程序,借助异步和事件驱动还有少量的线程垂直伸缩,而非横向伸缩(分布式集群)当Http连接缓慢的时候,从数据库到Http数据响应中也会 ...
- linux内核中预留4M以上大内存的方法
在内核中, kmalloc能够分配的最大连续内存为2的(MAX_ORDER-1)次方个page(参见alloc_pages函数, "if (unlikely(order >= ...
- yii 之增加数据
模型代码: <?php namespace app\models; use yii\db\ActiveRecord; class Test extends ActiveRecord{ publi ...
- nyoj_90_整数划分_201403161553
整数划分 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 将正整数n表示成一系列正整数之和:n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1. 正整数 ...
- 【Java】NIO中Selector的select方法源码分析
该篇博客的有些内容和在之前介绍过了,在这里再次涉及到的就不详细说了,如果有不理解请看[Java]NIO中Channel的注册源码分析, [Java]NIO中Selector的创建源码分析 Select ...
- 使用icomoon把svg图片生成字体图标
今天看了使用icomoon来将svg转换成图标字体,本来是不会使用别人给的svg,也不清楚具体的好处是什么,查了svg以后,越来越懵,svg挺好的为什么要转成图标字体呢. 一.SVG介绍 SVG 是一 ...
- 创建ROS工作空间和包
一.创建工作空间 mkdir -p ~/openni_ws/src cd ~/openni_ws catkin_make //在catkin工作空间(openni_ws)下catkin_ ...
- Centos7安装完成后一些小优化
1.修改ip地址.网关.主机名.DNS等 [root@localhost ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 #网 ...
- Hbase优化总结
1.JVM参数优化: –Xmn=12G –Xms=24G -Xmx=24G 根据实际机器情况调整,一般为整个机器内存的一半,同时建议regionServer的堆内存建议不要超过32G ; -XX: ...