资讯专栏INFORMATION COLUMN

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

feng409 / 3108人阅读

摘要:深入理解引擎的执行机制最近在反省,很多知识都是只会用,不理解底层的知识。在阅读之前,请先记住两点是单线程语言的是的执行机制。所以,是存在异步执行的,比如单线程是怎么实现异步的场景描述通过事件循环,所以说,理解了机制,也就理解了的执行机制啦。

深入理解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(事件队列)里的任务,只有在主线程空闲时才会执行。
所以:只有在满足

3s后

主线程空闲

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

到此,js引擎的执行机制解读完啦,前端的水很深,慢慢摸着吧
感谢文章的提供者:ziwei3749

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93481.html

相关文章

  • 10分钟理解JS引擎执行机制

    摘要:深入理解引擎的执行机制灵魂三问为什么是单线程的为什么需要异步单线程又是如何实现异步的呢中的中的说说首先请牢记点是单线程语言的是的执行机制。 深入理解JS引擎的执行机制 1.灵魂三问 : JS为什么是单线程的? 为什么需要异步? 单线程又是如何实现异步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.说说setTimeout 首先,请牢记2...

    zzbo 评论0 收藏0
  • 深入前端-彻底搞懂浏览器运行机制

    摘要:当这些异步任务发生的时候,它们将会被放入浏览器的事件任务队列中去,等到运行时执行线程空闲时候才会按照队列先进先出的原则被一一执行,但终究还是单线程。 浏览器是多进程的 showImg(https://segmentfault.com/img/remote/1460000019706956?w=815&h=517); Browser进程: 浏览器的主进程(负责协调、主控),只有一个。 负...

    YPHP 评论0 收藏0
  • 深入前端-彻底搞懂浏览器运行机制

    摘要:当这些异步任务发生的时候,它们将会被放入浏览器的事件任务队列中去,等到运行时执行线程空闲时候才会按照队列先进先出的原则被一一执行,但终究还是单线程。 浏览器是多进程的 showImg(https://segmentfault.com/img/remote/1460000019706956?w=815&h=517); Browser进程: 浏览器的主进程(负责协调、主控),只有一个。 负...

    Youngs 评论0 收藏0
  • 【进阶1-4期】JavaScript深入之带你走进内存机制

    摘要:引擎对堆内存中的对象进行分代管理新生代存活周期较短的对象,如临时变量字符串等。内存泄漏对于持续运行的服务进程,必须及时释放不再用到的内存。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导) 本周正式开始前端进阶的第一期,本周的主题是调用堆栈,今天是第4天。 本计划一共28期,每期重点攻克一个面试重难点,如果你还不了解本进阶计划...

    不知名网友 评论0 收藏0
  • 由setTimeout深入JavaScript执行环境异步机制

    摘要:图片转引自的演讲和两个定时器中回调的执行逻辑便是典型的机制。异步编程关于异步编程我的理解是,在执行环境所提供的异步机制之上,在应用编码层面上实现整体流程控制的异步风格。 问题背景 在一次开发任务中,需要实现如下一个饼状图动画,基于canvas进行绘图,但由于对于JS运行环境中异步机制的不了解,所以遇到了一个棘手的问题,始终无法解决,之后在与同事交流之后才恍然大悟。问题的根节在于经典的J...

    codeGoogle 评论0 收藏0

发表评论

0条评论

feng409

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<