美文网首页
js执行机制

js执行机制

作者: ITtian | 来源:发表于2017-11-22 12:00 被阅读21次

    面试官老喜欢出这种题目问你,请说下这段代码的输出,其中就会有坑,之所以说是坑是因为你不了解,懂了就是云淡风轻,不懂还是不懂,觉得遍地是坑,殊不知高手是可以飞的。

    js是单线程语言
    js是一门单线程语言,哪怕es6,7都出来了,也没有改变它是单线程这一核心,只是出现了多了一些语法糖而已,所以一切的js版本的多线程都是用单线程模拟出来的,一切的js多线程都是纸老虎

    js的执行机制是事件循环 Event Loop
    js任务分为两类:同步任务,异步任务
    当我们打开网站的时候,网页的渲染过程就是一大堆的同步任务,而像加载图片等耗时久的任务,就是异步任务。

    参考自别的文章.png

    上图的意思是:

    • 同步任务和异步任务分别进入不同的执行场所,同步的进入主线程,异步的进入Event Table并注册函数
    • 当指定的事情完成时,Event Table会将这个函数移入Event Queue
    • 主线程内的任务执行完毕时,会去Event Queue读取相应的函数,进入主线程执行。
    • 上述过程会不断的重复,也就是常说的Event Loop(事件循环)

    直接上代码分析:

    let data = [];
    $.ajax({
        url:www.javascript.com,
        data:data,
        success:() => {
            console.log('发送成功!');
        }
    })
    console.log('代码执行结束');
    

    分析:

    • ajax进入Event Table ,注册回调函数success
    • 执行console.log('代码执行结束')
    • ajax事件完成,回调函数success进入Event Queue
    • 主线程从Event Queue读取函数success并执行
    setTimeout(() => {
        task();
    },3000)
    console.log('执行console');
    

    分析:

    • 执行setTimeou发现是异步任务,进入Event Table,3s后将回调函数加入到Event Queue中,
    • 执行console.log('执行console')
    • 主线程执行结束,去Event Queue拿函数执行,发现没有,此过程不断的重复
    • 3S 后Event Queue中有了回调函数,主线程拿之并执行

    我们可以得知,setTimeout这个函数,是经过指定时间后,把要执行的任务加入到Event Queue中,又因为单线程任务是一个个执行的,如果前面的任务需要执行的时间太久,那么只能等着,导致真正的延迟时间远大于3S

    setTimeout(fn,0)的含义是,指定某个任务在主线程最早得到空闲时执行,意思是不用等多少秒了,直接加入到Event Queue中。

    setIntervalsetTimeout含义差不多,setInterval会每隔指定的时间将注册的函数置入Event Queue,

    除了广义的同步任务和异步任务,对任务有跟精细的定义:
    macro-task(宏任务): 包括整体代码script,setTimeout,setinterval
    micro-task(微任务): Promise,process.nextTick
    不同类型的任务会进入对应的Event Queue,比如setTimeoutsetInterval会进入相同的Event Queue。

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

    setTimeout(function() {
        console.log('setTimeout');
    })
    
    new Promise(function(resolve) {
        console.log('promise');
        resolve()   //不resolve()的话  then里面的回调是不会执行的
    }).then(function() {
        console.log('then');
    })
    
    console.log('console');
    

    分析:

    • 这段代码作为宏任务,进入主线程。
    • 先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述)
    • 接下来遇到了Promise,new Promise立即执行,then函数分发到微任务Event Queue。
    • 遇到console.log(),立即执行。
    • 好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务Event Queue里面,执行。
    • ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务Event Queue中setTimeout对应的回调函数,立即执行。
    • 结束。
    事件循环,宏任务,微任务的关系.png
    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,7,6,8,2,4,3,5,9,11,10,12。
    

    最后:

    • javascript是一门单线程语言
    • Event Loop是javascript的执行机制

    本文章用于学习总结,参考自ssssyoki 这一次,彻底弄懂 JavaScript 执行机制

    相关文章

      网友评论

          本文标题:js执行机制

          本文链接:https://www.haomeiwen.com/subject/bzdnvxtx.html