简单而面试中又常见的知识点:JS执行机制
console.log('1');
setTimeout(function() {
console.log('2');
process.nextTick(function() {
console.log('3');
})
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
});
process.nextTick(function() {
console.log('6');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
});
setTimeout(function() {
console.log('9');
process.nextTick(function() {
console.log('10');
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
});
console.log('程序开始执行~');
setTimeout(() => {
console.log('执行setTimeout~');
}, 1000);
console.log('程序执行结束~');
// 输出结果:
// 程序开始执行~
// 程序执行结束~
// ...1s(这里表示等待时间)
// 执行setTimeout~
console.log('程序执行开始~')
setTimeout(() => {
console.log('setTimeout执行啦~')
}, 3000);
sleep(5000);
console.log('程序执行结束~')
// 注:这里的sleep函数不是js的标准函数,只是表示一个执行需要5秒的函数。
// 输出结果:
// 程序执行开始~
// ...5s后
// 程序执行结束~
// setTimeout执行啦~
- process.nextTick,我们知道浏览器环境下的setTimeout,那么process.nextTick就相当于在node环境下执行的setTimeout。
- 宏任务和微任务,主线程一直在执行script代码,还有setTimeout、setInterval函数就是宏任务,而Promise.then,process.nextTick则是微任务。
console.log('程序执行开始~')
setTimeout(() => {
console.log('setTimeout执行啦~')
}, 3000);
new Promise((resolve) => {
console.log('promise开始执行~');
resolve();
}).then(() => {
console.log('promise执行结束~')
});
console.log('程序执行结束~')
// 输出结果:
// 程序执行开始~
// promise开始执行~
// 程序执行结束~
// promise执行结束~
// ...3s后
// setTimeout执行啦~
- 代码一开始执行,执行的就是全局代码,也就是宏任务的同步代码;
- 遇到console.log,直接执行,输出"程序执行开始~";
- 接着执行,遇到setTimeout函数,将其回调函数注册进宏任务的Event Queue(注意:宏任务和微任务分别有自己的Event Queue);
- 接着遇到new Promise,立刻执行(new Promise里面的函数是立刻执行的,只有.then函数里面才是放到微任务去执行的,不要搞混咯~),输出"promise开始执行~";
- 接着遇到promise.then函数,将其回调函数注册到微任务的Event Queue;
- 接着继续执行,遇到console.log,直接输出"程序执行结束~"
- 到这里,宏任务的同步代码就全部执行完毕了,这时候,js引擎会去检查微任务的Event Queue中是否存在回调函数,这时微任务的Queue中还有一个函数未执行,因此在这时候执行,输出"promise执行结束~";
- 当微任务的所有回调函数被执行完了之后,一次事件循环就结束了。
- 这时候js引擎会检查宏任务的Event Queue中是否还有未执行的函数,如果还有,将会开启下一轮的事件循环。由于此时我们宏任务的Event Queue中还有未执行的setTimeout,所以开启下一轮事件循环,执行setTimeout回调,输出"setTimeout执行啦~"
console.log('1')
setTimeout(() => {
console.log('2')
})
new Promise((resolve) => {
console.log('3')
resolve()
}).then(() => {
console.log('4')
})
process.nextTick(() => {
console.log('5')
})
new Promise((resolve) => {
console.log('6')
resolve()
}).then(() => {
console.log('7')
})
process.nextTick(() => {
console.log('8')
})
console.log('9')
// 输出结果
// 1 3 6 9 5 8 4 7 2
console.log('1');
setTimeout(() => {
console.log('2');
process.nextTick(() => {
console.log('3');
})
new Promise((resolve) => {
console.log('4');
resolve();
}).then(() => {
console.log('5')
})
});
process.nextTick(() => {
console.log('6');
})
new Promise((resolve) => {
console.log('7');
resolve();
}).then(() => {
console.log('8')
});
setTimeout(() => {
console.log('9');
process.nextTick(() => {
console.log('10');
})
new Promise((resolve) => {
console.log('11');
resolve();
}).then(() => {
console.log('12')
})
});
- 程序开始,执行宏任务同步代码,遇到console.log,输出:;
- 遇到setTimeout1,将其放入宏任务Event Queue中;
- 遇到process.nextTick1,放入微任务Event Queue中;
- 遇到new Promise,直接执行其中的代码,输出:;
- 遇到Promise.then1函数,将其放入微任务Event Queue;
- 继续执行,遇到setTimeout2,放入宏任务Event Queue;
- 此时任务队列状态:
- 宏Queue: setTimeout1,setTimeout2;
- 微Queue: process.nextTick1、Promise.then1;
- 至此,宏任务同步代码执行完毕,检测微任务队列是否存在任务,由于存在两个微任务,所以这时候执行微任务;
- 先执行process.nextTick1,输出:;
- 接着执行Promise.then1,输出: ;
- 微任务执行完毕后,一次事件循环结束,js引擎持续检测宏任务中是否存在任务,存在的话开启下一次事件循环;由于存在两个setTimeout,所以在满足setTimeout执行条件后,开启下一次事件循环,执行回调函数;
- 先执行setTimeout1,遇到console.log,输出:;
- 接着遇到process.nextTick2,放入微任务Event Queue;
- 继续执行遇到new Promise,直接执行,输出:;
- 然后遇到Promise.then2,放入微任务Event Queue;
- 至此setTimeout1执行完毕,此时任务队列状态:
- 宏Queue: setTimeout2;
- 微Queue: process.nextTick2、Promise.then2;
- js引擎检查微任务Event Queue中还存在两个微任务,因此执行这两个微任务;
- 先执行process.nextTick2,输出:;
- 接着执行Promise.then2,输出:;
- 微任务执行完毕,第二次事件循环结束;
- js引擎持续检查宏任务Event Queue中是否还有未执行函数,检测到还有setTimeout2未执行,因此开启第三轮的事件循环;
- 执行setTimeout2,遇到console.log,输出:;
- 又遇到process.nextTick3,放入微任务队列;
- 遇到new Promise,直接执行,输出:;
- 遇到Promise.then3,放入微任务队列;
- 至此,setTimeout2执行完毕,此时任务队列状态:
- 宏Queue: 无;
- 微Queue: process.nextTick3、Promise.then3;
- js引擎在检测是否存在未执行的微任务,由于还有两个微任务未执行,因此将其执行;
- 先执行process.nextTick3,输出:10;
- 接着执行Promise.then3,输出:12;
- 至此,微任务执行完毕,事件循环结束;
简单而面试中又常见的知识点:JS执行机制的更多相关文章
- 从一道看似简单的面试题重新理解JS执行机制与定时器
壹 ❀ 引 最近在看前端进阶的系列专栏,碰巧看到了几篇关于JS事件执行机制的面试文章,因为我在之前一篇 JS执行机制详解,定时器时间间隔的真正含义 博文中也有记录JS执行机制,所以正好用于作为测试自 ...
- 浏览器中js执行机制学习笔记
浏览器中js执行机制学习笔记 RiverSouthMan关注 0.0772019.05.15 20:56:37字数 872阅读 291 同步任务 当一个脚本第一次执行的时候,js引擎会解析这段代码,并 ...
- 前端js面试中的常见的算法问题
虽说我们很多时候前端很少有机会接触到算法.大多都交互性的操作,然而从各大公司面试来看,算法依旧是考察的一方面.实际上学习数据结构与算法对于工程师去理解和分析问题都是有帮助的.如果将来当我们面对较为复杂 ...
- Nginx面试中最常见的18道题 抱佛脚必备
Nginx的并发能力在同类型网页服务器中的表现,相对而言是比较好的,因此受到了很多企业的青睐,我国使用Nginx网站的知名用户包括腾讯.淘宝.百度.京东.新浪.网易等等.Nginx是网页服务器运维人员 ...
- nginx面试中最常见的18道题
1.请解释一下什么是Nginx? Nginx是一个web服务器和反向代理服务器,用于HTTP.HTTPS.SMTP.POP3和IMAP协议. 2.请列举Nginx的一些特性. Nginx服务器的特性包 ...
- 面试中linux常见的20个命令
1.查找文件 find / -name filename.txt 根据名称查找/目录下的filename.txt文件. 2.查看一个程序是否运行 ps –ef|grep tomcat 查看所有有关to ...
- 企业面试中关于MYSQL重点的28道面试题解答
问题1:char.varchar的区别是什么? varchar是变长而char的长度是固定的.如果你的内容是固定大小的,你会得到更好的性能. 问题2: TRUNCATE和DELETE的区别是什么? ...
- 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)
首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...
- 带你全面了解高级 Java 面试中需要掌握的 JVM 知识点
目录 JVM 内存划分与内存溢出异常 垃圾回收算法与收集器 虚拟机中的类加载机制 Java 内存模型与线程 虚拟机性能监控与故障处理工具 参考 带你全面了解高级 Java 面试中需要掌握的 JVM 知 ...
随机推荐
- HBase可用性分析与高可用实践
HBase作为一个分布式存储的数据库,它是如何保证可用性的呢?对于分布式系统的CAP问题,它是如何权衡的呢? 最重要的是,我们在生产实践中,又应该如何保证HBase服务的高可用呢? 下面我们来仔细分析 ...
- MySQL之视图、触发器、函数、存储过程、索引
1.视图 把某个查询语句(临时表)设置别名,日后方便使用,视图是虚拟的(不要在数据库里使用视图) #创建: create view v1(视图名称) as SQL #修改: alter view v1 ...
- 随笔之——伪类选择器:nth-child(n) 与 nth-of-type(n)的区别!!!
话不多说!直接正题!!! 一.E:nth-child(n)///选中父元素中第(n)个元素.若第n个元素为E则选中:若第n个不为E则不选中.n可以为2n(偶数).2n+1(奇数).等... 二.E:n ...
- C/C++ 程序执行时间
C/C++中的计时函数是clock(),而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下: clock_t clock( void ); 这个函数返回从“开启这个程序进 ...
- Spring boot自定义parent POM
文章目录 概述 不使用Parent POM来引入Spring boot 覆盖依赖项版本 概述 在之前的Spring Boot例子中,我们都会用到这样的parent POM. <parent> ...
- Java5-7作业总结(第八次作业)19201421-吴志越
前言:关于此次三次作业,相比于前3次难度着实高了一个档次,第五次作业,虽然对于工具类没有很高.但是第一题的复杂程度很高,对于正则表达式有很高的要求,需要使用很多正则表达式的方法,而且不能有一处错误,对 ...
- 使用3种协议搭建本地yum仓库
关闭防火墙和selinux [root@qls yum.repos.d]# systemctl stop firewalld (stop,start,disable,enable) [root@qls ...
- 模块sys,os
Python的强大之处在于他有非常丰富和强大的标准库和第三方库,几乎你想实现的任何功能都有相应的Python库支持,以后的课程中会深入讲解常用到的各种库,现在,我们先来象征性的学2个简单的. 在Pyt ...
- Leetcode 1. 两数之和 (Python版)
有粉丝说我一个学算法的不去做Leetcode是不是浪费,于是今天闲来没事想尝试一下Leetcode,结果果断翻车,第一题没看懂,一直当我看到所有答案的开头都一样的时候,我意识到了我是个铁憨憨,人家是让 ...
- CF #636 (Div. 3) 对应题号CF1343
unrated 选手悠闲做题,然后只做出四个滚蛋了 符合 div3 一贯风格,没啥难算法 E最后就要调出来了,但还是赛后才A的 CF1343A Candies 传送门 找到一个 \(x\),使得存在一 ...