• 技术文章 >web前端 >js教程

    深入理解JavaScript执行机制

    不言不言2018-08-31 10:12:23原创462
    本篇文章给大家带来的内容是关于深入理解JavaScript执行机制,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

    首先我们大家都了解的是,JavaScript 是一门单线程语言,所以我们就可以得出:

    JavaScript 是按照语句顺序执行的

    首先看:

    let a = '1'
    console.log(a)
    
    let b = '2'
    console.log(b)

    这个显然大家都知道结果,依次输出1,2

    然而换一种:

    setTimeout(function() {
        console.log(1)
    })
    
    new Promise(function(resolve) {
        console.log(2)
        for(var i = 0;i< 10;i++){
            i === 10 && resolve()
        }
    }).then(function() {
        console.log(3)
    })
    console.log(4)

    这个时候再看代码的顺序执行,输出1,2, 3, 4。好了放到浏览器运行一下,什么?输出居然是 2, 4, 3,1。说好的按顺序执行呢?下面就需要去了解一下 JavaScript 的执行机制问题了。

    单线程

    首先JavaScript 是一门单线程的语言,在最新的HTML5 推出的 Web-worker,但是 JavaScript 是一个单线程的语言这一个核心还是没有改变。所以,JavaScript 的多线程都是基于单线程模拟出来的。所以牢记 JavaScript 是单线程语言。

    事件循环

    任务分为两类:

    当我们打开页面时,页面的渲染就是一大堆同步任务,而像加载图片和音频资源耗时的任务,就是异步任务。时间循环的主要内容就是:

    1. 当任务进入执行栈的时候,判断是同步任务还是异步任务,如果是同步任务,进入主线程进行执行,异步进入 Event Table 进行注册函数。

    2. 当指定的事件完成后,Event Table 将这个函数移入到事件队列

    3. 主线程中的任务执行完毕后,去任务队列读取对应的函数,进入主线程执行

    4. 上述的过程不断重复,也就构成了事件循环

    其中js引擎存在一个监控进程,不断检查主线程执行栈是否为空,一旦为空,就会去时间队列那检查有没有等待被调用的函数。

    例如:

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

    这也就是为什么即使设置setTimeout(fn, 0)函数也不会立即执行的原因。不过即使主线程为空,0ms也是达不到的,根据HTML标准,最低是4ms。

    setInterval

    还有一个与setTimeout类似的函数,对于setInterval来说,是循环执行。对于执行顺序来说,setInterval会每隔指定的时间将注册的函数置入Event Queue,如果前面的任务耗时太久,那么同样需要等待。

    但是需要注意的一点是,对于setInterval(fn, ms)来说,他并不是每过ms执行一次 ,而是每过 ms 会有fn进入任务队列。也就是说如果setInterval 的回调函数的执行事件如果超过延迟ms,那么就看不出来事件间隔了。

    Promise 和 process.nextTick(callback)

    除了广义的同步任务和异步任务之外,还有对任务更精细的划分,分为:

    事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

    用一段代码来说明:

    setTimeout(function() {
        console.log('1');
    })
    
    new Promise(function(resolve) {
        console.log('2');
        resolve()
    }).then(function() {
        console.log('3');
    })
    
    console.log('4');

    好了了解了基本的原理之后,我们来看一个更复杂的:

    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')
        })
    })

    不知道大家答案是什么?接下来我们来进行分析一下:

    第一轮:

    1. 首先整段代码作为一个宏任务进入主线程,首先遇到console.log()输出1

    2. 遇到第一个setTimeout()进入宏任务队列

    3. 遇到Process.nextTick()进入微任务队列

    4. 然后遇到Promise,立即执行,输出7,then被添加到微任务队列

    5. 遇到第二个setTimeout,进入宏任务队列

    6. 然后执行两个微任务

    7. 执行Process.nextTick()输出6

    8. 执行then,输出8

    这样第一轮循环就彻底结束了,进行第二轮事件循环,也就是第一个setTimeout

    1. 首先遇到console.log(),输出2

    2. 遇到Process.nextTick(),进入微任务队列

    3. 遇到Promise立即执行输出4,then进入微任务队列

    4. 然后执行第一个微任务,输出3

    5. 执行then,输出5

    这样第二轮事件循环就结束了,最后执行第二个setTimeout,第二个setTimeout和上面原理类似,也就不重复说明了。所以最终结果是:1,7,6,8,2,4,3,5,9,11,10,12

    相关推荐:

    js执行机制实例详解

    JavaScript运行机制之Event Loop

    以上就是深入理解JavaScript执行机制的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:javascript
    上一篇:javascript匀速运动实现侧边栏分享效果(代码) 下一篇:javascript匀速运动实现淡入淡出的效果(代码)
    Web大前端开发直播班

    相关文章推荐

    • js执行机制实例详解• 浅析JS执行机制• js引擎的执行机制详解• js执行机制的概念?js的执行机制的实现方法

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网