• 技术文章 >web前端 >前端问答

    完全掌握JavaScript执行机制

    长期闲置长期闲置2022-01-20 17:58:50转载236
    本篇文章给大家带来了关于JavaScript执行机制的相关问题,其中包括JavaScript单线程和JavaScript同步异步的相关知识,希望对大家有帮助。

    一、为什么JavaScript是单线程

    如果想了解JavaScript为什么是单线程的,我们就要从JavaScript是用来做什么工作的来入手。

    JavaScript作为浏览器的脚本语言,产出的目的就是为了浏览器与用户进行交互,操作DOM元素,从而提升用户的交互及体验感。JavaScript要操作浏览器的DOM元素,因此导致JavaScript无法成为多线程语言,我们假设一个场景,如果JavaScript是多线程语言,两个线程同时操作一个DOM元素,一个线程需要编辑更新DOM元素,而另一个则是删除DOM元素节点,这是浏览器应该以哪个为准呢?

    同一时间只能做同一件事情,因为操作DOM元素的原因,导致单线程是JavaScript这门语言的核心,也是这门语言特点。

    HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。即使这样的改动也并没有改变js单线程的本质。

    二、JavaScript中的同步与异步

    javaScript的单线程机制,就导致同一时间只能做一件事情。就像一堆人在ATM取款机取款,即使后面再多的人在着急,也只能一个一个的排队,等待前一个人取完款,才能轮到后一人。

    可是这样会导致如果说前一个任务消耗时间过长,后一个任务就会等待非常久,比如,我们需要加载一个数据量非常大的Ajax请求,我们不得不等待请求相应结果,再继续往下行执后续任务。

    那我们该如何处理这种情况呢?既然我们无法改变JavaScript的单线程机制,我们是否可以将一些耗时久的任务进行暂时挂起,等到主任务执行完成之后,再将这些挂载的任务执行。JavaScript的作者也想到了这样的方式,JavaScript拥有了同步任务与异步任务。

    同步任务就是,任务在主线程上进行排队,下一个任务必须等待上一个任务执行完成,才可以执行。而异步任务是指,任务不进入主线程,而进入任务队列(task queue)进行等待,进入任务队列的任务只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

    三、Event Loop事件循环机制

    JavaScript的所有同步任务都在主线程上执行,形成一个执行栈。

    任务队列是先进先出的原则,先进队列的事件先执行,后进队列的事件后执行。

    Event Loop

    如此反复,这样就形成了一个无限的循环(event loop)。(下图来自网络)

    38.png

    学习了 Event Loop 我们一起来看看下面这道题:

    setTimeout(function(){
         console.log('setTimeout start')
     });
     new Promise(function(resolve){
         console.log('promise start');
         resolve()
     }).then(function(){
         console.log('promise then')
     });
     console.log('script end');

    尝试按照,上文我们刚学到的JavaScript执行机制去分析

    1. 首先执行同步任务,执行到setTimeout,但是setTimeout是异步任务的暂时挂起,等待计时超时,添加进任务队列中。

    2. 继续往下,在执行到new Promise,new Promise里面的是同步任务,打印 "promise start"。

    3. 在执行到resolve将.then添加进任务队列中。

    4. 在执行 console.log('script end');打印"script end"。

    5. 这时主任务都已经执行完成,在将异步任务添加进主任务中直接执行,打印"setTimeout start",再将.then添加进主任务中,打印"promise then"。

    所以结果应该是:promise start -> script end -> setTimeout start -> promise then 吗?

    亲自在浏览器执行后,结果居然不是这样,而是 promise start -> script end -> promise then -> setTimeout start

    宏任务与微任务

    那为什么上文中的结果为什么跟我们预想的不一致,为什么 setTimeout start 会在 promise 之后打印。

    其实是因为异步的执行也是有先后顺序的。其实用异步跟同步的方式去划分任务队列的执行顺序是不准确的。应该划分为 微任务 与 宏任务。

    所以说setTimeout是异步任务中的 宏任务 ,而Promise是异步任务中的 微任务 。不管是 微任务 还是 宏任务,都会进入相应的 Event Queue, 接下来我们在看一个流程图。

    39.png

    我们来稍微理解一下:

    这便也是 javaScript 的运行机制,结合这个我们再重新的分析一下上面的例子。

    永远记住JavaScript是单线程,以前是、现在是、将来也会是。所有的多线程说法都是扯淡。

    即使是Event Queue,也只不是实现异步的方式,也是js的执行机制。

    以后能用JavaScript实现的。都将会用JavaScript来实现。

    相关推荐:javascript学习教程

    以上就是完全掌握JavaScript执行机制的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:掘金,如有侵犯,请联系admin@php.cn删除
    专题推荐:javascript 前端 html
    上一篇:怎样给select添加css样式 下一篇:css怎么设置按钮中的字大小
    php培训_php实战培训【立即报名】-php中文网第20期

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• jsp和javascript之间啥关系• lua与javascript的区别是什么• JavaScript中有点击事件吗• javascript脚本由什么解释和执行• 怎么用javascript判断是否是闰年
    1/1

    PHP中文网