博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入理解js引擎的执行机制
阅读量:6504 次
发布时间:2019-06-24

本文共 3712 字,大约阅读时间需要 12 分钟。

深入理解js引擎的执行机制

最近在反省,很多知识都是只会用,不理解底层的知识。所以在开发过程中遇到一些奇怪的比较难解决的bug,在思考的时候就会收到限制。所以,在这里一点一点补充基础知识吧。

在阅读之前,请先记住两点:

  • js是单线程语言
  • js的Event Loop是js的执行机制。深入理解js的执行,就等与深入理解js的Event Loop

好啦,下面进入正题

1. 灵魂三问:js为什么是单线程的?为什么需要异步?单线程又是怎么实现异步的呢?

技术的出现,都跟现实世界里的场景密切相关。同样的,我们就结合现实场景,来回答这三个问题。

(1)js为什么是单线程的?

        js是一种脚本语言,脚本语言是为了缩短传统的编写-编译-链接-运行过程而创建的计算机编程语言,脚本语言不需要编译,可以直接用,由解释器来负责解释。

        js最初被设计用在浏览器中,那么想象一下,如果浏览器中的js是多线程的。。。
场景描述:
        现在有两个进程:process1和process2,由于是多线程的js,所以它们对同一个DOM同时进行操作process1删除了该DOM,而process2编辑了该DOM,同时下达了两个矛盾的命令,你这让浏览器怎么执行呢?
        这样一想,是不是就理解了js为什么被设计成单线程了吧~~~


(2)js为什么是异步的?

场景描述:

        如果js不存在异步,只能自上而下执行,如果上一行执行时间很长,比如说没有网了,那么下面的代码就会被阻塞,对于用户来说,阻塞就意味着“卡死”,这样导致用户体验很差。由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行。
        所以,js是存在异步执行的,比如setTimeout、setInterval、ajax、promise


(3)单线程是怎么实现异步的?

场景描述:

        通过Event Loop(事件循环),所以说,理解了Event Loop机制,也就理解了js的执行机制啦。

2. js中的Event Loop第一课

举个栗子:观察下它的执行机制

console.log(1)setTimeout(function(){    console.log(2)},0);console.log(3)

毫无疑问:运行结果是1 3 2

也就是说:setTimeout里的函数并没有立即执行,而是延迟了一段时间,满足一定条件后才去执行的,我们叫做异步代码。

所以这里我们首先知道了js里的一种分类方式,就是将任务分为:同步任务和异步任务。

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

  • 首先判断js是同步的还是一步的,同步的就进入主进程,异步的就进入event table(事件表)
  • 异步任务在Event table中注册函数,当满足触发条件后,被推入event queue(事件队列)
  • 同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行的异步任务,如果有就推入主进程中

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

所以上面的栗子,你是否可以描述它的执行顺序了呢?

console.log(1)          //是同步任务,放进主进程里setTimeout(function(){  //是异步任务,放进event table,0s之后被推入event queue里    console.log(2)},0);console.log(3)          //是同步任务,放进主进程里//当1、3在浏览器控制台被打印后,主线程去event queue中查看是否有可执行的函数,执行setTimeout里的函数。

3. js中的Event Loop第二课

所以,上面关于Event Loop就是我对js执行机制的理解,是不是很简单呢。。。。

慢着!看看下面的这段代码
又一个栗子:

setTimeout(function(){    console.log("定时器开始啦~~~");})new Promise(function(resolve){    console.log("马上执行for循环啦");    for(var i=0;i<10000;i++){        i==99&&resolve();    }}).then(function(){    console.log("执行then函数啦")});console.log("表演完毕!");

有没有很熟悉,好像面试过程中经常碰见这种问题呀~~~

现在,我们按照上面学到的js执行机制去分析一下下

setTimeout(function(){                 //是异步任务,被放进event table中    console.log("定时器开始啦~~~");})new Promise(function(resolve){         //是同步任务,被放进主进程中,直接执行    console.log("马上执行for循环啦");    for(var i=0;i<10000;i++){        i==99&&resolve();    }}).then(function(){                    //是异步任务,被放进event table中    console.log("执行then函数啦")});console.log("表演完毕!");              //是同步任务,被放进主进程中,直接执行

运行结果是:【马上执行for循环啦----表演完毕!----执行then函数啦----定时器开始啦~~~】

那么,难道是异步任务的执行顺序不是前后顺序,而是另有规定?事实上,按照同步和异步的划分方式,并不准确。

所以这里我们首先知道了js里的一种分类方式,就是将任务分为:同步任务和异步任务。

叨叨了半天,原来都是一些“假大空”的东西,搞什么搞嘛,哼!!!

准确的划分方式是:

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

图片描述

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

执行一个宏任务,执行过程中如果遇到微任务,就将其放在微任务的event queue里

当前宏任务执行完成后,会查看微任务的event queue,并将里面的全部微任务依次执行完。
重复以上两个步骤,结合Event Loop第一课和Event Loop第二课,就是更为准确的js执行机制了。
尝试按照刚才学到的执行机制,去分析第二个栗子:

setTimeout(function(){                  console.log("定时器开始啦~~~");})new Promise(function(resolve){         console.log("马上执行for循环啦");    for(var i=0;i<10000;i++){        i==99&&resolve();    }}).then(function(){                   console.log("执行then函数啦")    });console.log("表演完毕!");              //首先执行script中的宏任务;//遇到setTimeout,放进宏任务的event queue中;//遇到new Promise直接执行,打印“马上执行for循环啦”;//遇到then方法,是微任务,被放进微任务的event queue//执行打印“表演完毕!”,本轮宏任务执行完毕;//查看本轮微任务,发现then方法里的函数,执行打印“执行then函数啦”//到此,本轮Event Loop全部完成//下一轮循环里,先执行一个宏任务,发现宏任务的event queue中有一个setTimeout中的函数,打印“定时器开始啦”

运行结果是:【马上执行for循环啦----表演完毕!----执行then函数啦----定时器开始啦~~~】

4.谈谈setTimeout

下面这段setTimeout代码是什么意思?我们一般说:“3s后,会执行setTimeout里的函数”

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

但是这种说法并不严谨,准确的解释是:

        3s后,setTimeout里的函数会被推入到event queue中,而event queue(事件队列)里的任务,只有在主线程空闲时才会执行。
所以:只有在满足

  1. 3s后
  2. 主线程空闲

这两个条件同时满足,才会在3s后执行该函数。如果主线程执行内容很多,执行时间超过3s,比如执行了10s,那么这个函数只有在10s后执行啦


到此,js引擎的执行机制解读完啦,前端的水很深,慢慢摸着吧

感谢文章的提供者:ziwei3749

转载地址:http://kdqyo.baihongyu.com/

你可能感兴趣的文章
贵阳高新区力争打造“千亿级大数据园区”
查看>>
安防众筹不止于卖产品 思维拓展刺激消费
查看>>
OpenSSH曝高危漏洞 会泄露私钥
查看>>
艾特网能获2016APCA用户满意品牌大奖
查看>>
《软件工艺师:专业、务实、自豪》一2.4 《敏捷软件开发宣言》
查看>>
《CCNP TSHOOT 300-135学习指南》——第2章 结构化故障检测与排除进程
查看>>
《Java EE 7精粹》—— 2.5 非阻塞I/O
查看>>
《Python数据科学实践指南》一2.2 字符串
查看>>
《R数据可视化手册》——1.1 安装包
查看>>
《iOS创意程序设计家》——导读
查看>>
spring-aop
查看>>
android RecycleView Adapter简单封装
查看>>
PgSQL · 案例分享 · 递归收敛优化
查看>>
Dart的数据库操作
查看>>
Codeforces 591 B Rebranding【Codeforces Round #327 (Div. 2)】
查看>>
命名难,难于上青天
查看>>
做完和做好不一样
查看>>
APUE读书笔记-05标准输入输出库(7)
查看>>
23 第一周作业
查看>>
DNS解析偶尔延迟
查看>>