关于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. 【2018.10.20】noip模拟赛Day3 二阶和

    今年BJ省选某题的弱化版…… 这看起来就没那么难了,有几种方法维护,这里提两种. 第一种(傻逼的我写的) 维护 一维&二维前缀和. 对于一个长度为$m$的序列$b_1,b_2,...,b_m$ ...

  2. SpringBoot项目整合Druid进行统计监控

    0.druid介绍,参考官网 1.在项目的POM文件中添加alibaba的druid依赖 <dependency> <groupId>com.alibaba</group ...

  3. 简单说明PHP的垃圾收集机制是怎样的?

    腾讯 对变量有个引用计数,计数到0时变量被销毁. ———————————————————————— 每一种语言都有自己的自动垃圾回收机制,让程序员不必过分关心程序内存分配,但是在OOP中,有些对象需要 ...

  4. laravel 查询构造器2

    //查询构造器 public function query() { //获取所有的数据 $student = DB::table('student')->get(); var_dump($stu ...

  5. web信息搜索之目标扫描篇

    https://blog.csdn.net/dongfei2033/article/details/78175421

  6. Unable to locate Attribute with the the given name [] on this ManagedType

    最近在写Springboot+hibernate的项目,遇到这个问题 好坑,查了半天没发现我哪里配置错了,后来发现实体类声明字段大小写敏感,把声明字段改成小写就行了

  7. HDU - 5973 Game of Taking Stones (威佐夫博弈 高精度)

    题目描述: Two people face two piles of stones and make a game. They take turns to take stones. As game r ...

  8. codevs科技庄园

    /* 因为每一秒只能走一个单位长度,而每走一个单位长度又会消耗一个体力值,如果体力值没有了时间还有也只能按照体力值计算,反之一样,所以V对于时间和体力值取小 cnt记录有桃子的树的个数,node[cn ...

  9. android EditText监听和长度监测事件

    <?xml version="1.0" encoding="utf-8"?> <!-- 定义基础的LinearLayout布局 --> ...

  10. JNI之—— Eclipse配置C/C++开发环境

    转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46622173 开发环境:Eclipse3.2.CDT3.1.MinGW5.1 1. ...