首先明确两点:

1.JS 执行机制是单线程。

2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行。

单线程执行带来什么问题?

在JS执行中都是单线程执行,所以代码的执行可以说是自上而下,如果前一段的代码出现问题,就会导致下一段代码无法执行,对于用户而言就是卡死现象,所以在JS执行机制引出了异步执行操作。

那异步能解决什么呢问题,又会带来什么问题?

异步操作能够很好的解决上面单线程执行出现的卡死现象,但是也会产生问题,比如同时对一件事情操作,不知道应该先执行那件事。

那么同步中使用异步如何实现呢?

是通过的事件循环(Event loop)那先了解下Event loop吧。

先看一下,以下代码(1)

注意观察执行顺序

console.log("1");
setTimeout(()=>{
console.log("2");
},0);
console.log("3");

有点JS 基础的同学会容易就知道了运行结果。

运行结果是:1、3、2

大家都知道setTimeout里的函数并没有立即执行,而是延迟一段时间,符合特定的条件才开始执行,这就是异步执行操作。

由此执行我们先了解到JS任务的执行分类为:同步任务和异步任务。

按照这种的分类方式JS的执行机制是:

首先,判断JS是同步还是异步,同步进入主线程,异步进入Event table

其次,异步任务在Event table中注册函数,当满足特定的条件,被推入Event queue

最后,同步任务进入主线程后一直执行,直到主线程空闲后,才会去Event queue中查看是否有可执行的异步任务,如果有就推入主线程中执行。

循环以上三步执行,这就是Event loop。

所以上面的例子的执行顺序是

console.log("1")是同步任务,放入主线程,
setTimeout()是异步任务,被放入Event table,0秒后被推入Event queue里,
console.log("3")是同步任务,放入主线程 当1、3任务先执行完后,主线程去Event queue(事件队列)里查看是否有可执行的函数,执行setTimeout里的函数。 所以,上面关于Event loop就是我对JS执行机制的理解,直到遇到了下面这段代码(2)。
setTimeout(()=>{
console.log("定时器开始执行");
}) new Promise(function(resolve){
console.log("准备执行for循环了");
for(var i=0;i<100;i++){
i==22&&resolve();
}
}).then(()=>console.log("执行then函数")); console.log("代码执行完毕");

那我们也按着上面总结的JS执行分类分析:

setTimeout 是异步任务,被放到event table
new Promise 是同步任务,被放到主进程里,直接执行打印 console.log('马上执行for循环啦')
.then里的函数是 异步任务,被放到event table
console.log('代码执行结束')是同步代码,被放到主进程里,直接执行

所以最后的执行结果是:【准备执行for循环-->代码执行完毕-->定时器开始执行-->执行then函数 】,对吗?

最后执行后发现结果并非是你想的这样,而是【准备执行for循环-->代码执行完毕-->执行then函数-->定时器开始执行】,为什么会是这样呢?难道是异步任务执行的顺序不是前后顺序,而是另有规定?事实上,按照异步同步的划分并不准确。

而准确的方式应该是:

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

按照上图这种分类方式:JS 的执行机制是:

  • 执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里
  • 当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完

重复以上2步骤,结合event loop(1) event loop(2) ,就是更为准确的JS执行机制了。

按照这种执行机制,去分析第二段代码

首先执行script下的宏任务,遇到setTimeout,将其放到宏任务的【队列】里
遇到 new Promise直接执行,打印"准备执行for循环"
遇到then方法,是微任务,将其放到微任务的【队列里】
打印 "代码执行完毕"
本轮宏任务执行完毕,查看本轮的微任务,发现有一个then方法里的函数, 打印"执行then函数"
到此,本轮的event loop 全部完成。
下一轮的循环里,先执行一个宏任务,发现宏任务的【队列】里有一个 setTimeout里的函数,执行打印"定时器开始执行"

所以最后的执行顺序就是:【准备执行for循环-->代码执行完毕-->执行then函数-->定时器开始执行】

最后再说一下setTimeout

先看一段代码

我们一般说这段代码,在3秒后执行setTimeout内的函数。

setTimeout(function(){
console.log('执行了')
},3000)

但这种说法往往是不够严谨的,准确的解释是:3秒后,setTimeout函数会被推入Event queue(事件队列),而Event queue(事件队列)内的任务,只有在主线程空闲时才会执行。

所以,只有同时满足以下条件setTimeout内的函数才能被执行

1.3秒后

2.主线程空闲时

若主线程的执行任务很多,执行时间超过3秒,比如说5秒,那么setTimeout内的函数只能在5秒后执行了

原文

 
 
 

深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)的更多相关文章

  1. 深入理解JS引擎的执行机制

    深入理解JS引擎的执行机制 1.灵魂三问 : JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4 ...

  2. 10分钟理解JS引擎的执行机制

    首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 (1) JS为什么是单线 ...

  3. 理解JS引擎的执行机制

    首先,请牢记2点: (1) JS是单线程语言 (2) JS的Event Loop是JS的执行机制.深入了解JS的执行,就等于深入了解JS里的event loop 1.灵魂三问 : JS为什么是单线程的 ...

  4. 前端读者 | 由setTimeout引发的JS引擎运行机制的研究

    本文来自 @xiaoyuze88 链接:http://xiaoyuze88.github.io/ 太久没碰代码了,那天想到关于循环调用setTimeout实现每隔一秒输出递增的数的那个问题,搞了搞,发 ...

  5. 初步理解JS的事件机制

    一.事件流(捕获,冒泡)   事件流:指从页面中接收事件的顺序,有冒泡流和捕获流. 当页面中发生某种事件(比如鼠标点击,鼠标滑过等)时,毫无疑问子元素和父元素都会接收到该事件,可具体顺序是怎样的呢?冒 ...

  6. 深入理解 js this 绑定机制

    函数调用位置 与词法作用域相反的是,this的指向由函数运行时决定,它是动态的,随着函数调用位置变化而变化. 要理解 this,首先要理解调用位置:调用位置就是函数在代码中被调用的位置(而 不是声明的 ...

  7. 27、理解js的继承机制(转载自阮一峰)

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  8. JAVA NIO中selectedKeys返回的键集,对其中的SelectionKey执行操作之后,是否需要在selectedKeys()中对其执行remove 操作

    今天一个东西需要用到java nio的东西.在网上查了一下资料,发现有Apache的Mina,Netty等,感觉JDK中带的NIO有点鸡肋啊.之前看过这部分的内容,但好长一段时间没有用,也就忘得七七八 ...

  9. js为什么是单线程的?10分钟了解js引擎的执行机制

    深入理解JS引擎的执行机制 1.JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.说说setT ...

随机推荐

  1. 启动weblogic服务时,还需要输入用户名和密码的解决方法

    当启动weblogic服务时,还需要输入用户名和密码,相当繁琐,如下: 而在生产环境中,一般会要求不要在每次启动时都输入用户名密码, 因此可以通过一些简单的配置达到此目的,通常的做法有两种: 1.修改 ...

  2. [20180316]共享服务模式和直接路径读.txt

    [20180316]共享服务模式和直接路径读.txt --//在共享服务器模式下,执行计划不会选择直接路径读,通过例子证明. 1.环境:SYS@book> @ &r/ver1PORT_S ...

  3. 洗礼灵魂,修炼python(28)--异常处理(2)—>运用异常

    你可能会想,卧槽这标题取的,前面不是说异常就是报错吗?异常还能运用? 是的,异常确实可以运用,可以刻意制造异常,在出现异常时捕获异常并对异常处理,所以进入本篇博文的话题—异常处理 异常处理: 异常处理 ...

  4. mongodb 配置文件

    本文档是在mongodb为3.4下编写的,仅作为参考,详细内容请参考:https://docs.mongodb.com/manual/reference/configuration-options/# ...

  5. DMZ 区域

    下面对DMZ区域进行简要介绍:DMZ是网络的一个区域,介于外网与内网之间的一个特殊区域,也称隔离区.它不同于传统的防火墙设置,DMZ防火墙方案为要保护的内部网络增加了一道安全防线,通常认为是非常安全的 ...

  6. OpenLdap 对接内部系统(Gitlab+Wiki+Jumpserver+Openvpn)配置

    LDAP 全称轻量级目录访问协议(英文:Lightweight Directory Access Protocol),是一个运行在 TCP/IP 上的目录访问协议.目录是一个特殊的数据库,它的数据经常 ...

  7. Linux之特殊的环境变量IFS以及如何删除带有空格的目录

    1.IFS是什么? Linux下有一个特殊的环境变量叫做IFS,叫做内部字段分隔符(internal field separator).IFS环境变量定义了bash shell用户字段分隔符的一系列字 ...

  8. PLS-00306: 调用 'SYNCRN' 时参数个数或类型错误

    System.Data.OracleClient.OracleException (0x80131938): ORA-00604: 递归 SQL 级别 1 出现错误 ORA-06550: 第 1 行, ...

  9. VS2015安装与C++进行简单单元测试

    1:VS2015是微软最新发布的编译器,http://www.itellyou.cn/这是我们的北航大神助教提供的下载网址,以前我们都是自己在网上找,找到的总不是那么如意,这下大神助教提供的网址就好好 ...

  10. HDU 2865 Birthday Toy

    题目链接 题意:n个小珠子组成的正n边形,中间有一个大珠子.有木棍相连的两个珠子不能有相同的颜色,旋转后相同视为相同的方案,求着色方案数. \(\\\) 先选定一种颜色放在中间,剩下的\(k-1\)种 ...