從簡單的面試題入手瞭解js的運行機制

你們可能都遇到過相似的面試題node

console.log(1);
setTimeout(()=>{
    console.log(3)
},0);
console.log(2);
複製代碼

結果輸出爲 1   2  3面試

爲何結果不是1,3,2呢,咱們明明只設置了0毫秒的延遲,下面讓咱們來看看究竟是怎麼回事ajax


首先先用大白話簡單介紹幾個概念promise

咱們都知道js是單線程的,什麼是單線程,說白了就是js在同一時間只能作一件事,這就是單線程瀏覽器

那麼什麼是任務隊列呢,咱們都知道事件、ajax這些是異步操做,當我點擊某個按鈕時會經過回調函數執行某些操做,當我去請求接口的時候瀏覽器不用一直等着,它能夠去作別的事情,當請求成功時會自動調起成功回調,那麼這和js的單線程看起來是衝突的,那它又是怎麼作到的呢,其實就是任務隊列bash

說到任務隊列這麼還有概念,同步任務,異步任務, 像settimeout,ajax,promise這種就屬於異步任務,像上述代碼中的console.log(1)就屬於同步任務網絡

js代碼是從上到下執行的,遇到異步任務要掛起,也就是說上面代碼的settimeout會先掛起,先不執行,此時代碼繼續向下執行console.log(3),當同步任務都執行完成後纔會去執行異步任務異步

因此剛纔輸出的結果是 1,2,3函數

下面咱們來看下一道題oop

console.log("a")
while(1){
    
}
console.log("b")複製代碼

只打印出a, 由於都是同步任務,while循環會一直執行,全部打印不出來b

那麼咱們再來看一道題

console.log("a");
setTimeout(()=>{
    console.log("b")
},0);
while(1){}複製代碼

仍是會只打印a,由於異步任務會當放到同步任務以後執行,因此b仍是打印不出來

接下來再看一道題

for(var i=0;i<4;i++){
  setTimeout(()=>{
        console.log(i)
    },0)
}複製代碼

最終會輸出 4,4,4,4,for循環是一個同步任務,會先執行,此時會把setTimeout交給瀏覽器的time模塊(主要是處理setTimeout,setInterval的),用不了1毫秒,循環執行完成,而此時r任務隊列裏尚未任務,只有setTimeout的時間(雖然咱們設置的是0,但瀏覽器最小大概是4毫秒)到了,瀏覽器的Time模塊纔會把setTimeout的回調函數放到任務隊列裏,任務隊列再等待一個叫event loop(後面會講) 的東西來執行,這道題講的是異步任務的放入時間和執行的時間


什麼是event loop

                  


執行棧(stack)會執行同步任務,當遇到異步任務,瀏覽器的js引擎會將異步任務拿走,好比setTimeout,瀏覽器的time模塊會將setTimeout拿走,當時間到了,會把回調函數放到任務隊列(callback queue),當同步任務執行完成後,js引擎會去任務隊列裏看看有沒有要執行的東西,發現裏面有東西就會把它拿到執行棧中執行,此時setTimeout就變成了執行棧中的同步任務,當setTimeout執行完,執行棧又空了,js引擎會去任務隊列中看看有沒有其餘須要執行的任務,如此往復的過程就是event loop


異步任務有哪些

setTimeout,setInterval

DOM事件

promise 

MutationObserve

MessageChannel等



看下面代碼

console.log(1);
setTimeout(function(){
    console.log(2);
});
Promise.resolve(1).then(function(){
    console.log('promise')
})複製代碼

會輸出 1 , promise , 2

由於異步任務中又分爲宏任務和微任務


微任務包括

promise裏的then,

MutationObserve

MessageChannel

宏任務包括

setTimeout,setInterval

在瀏覽器端微任務的執行會優先於宏任務,而在node裏會怎麼樣呢

再來看一段代碼

console.log(1);
setTimeout(function(){
    console.log(2);
    Promise.resolve(1).then(function(){
        console.log('promise')
    })
})
setTimeout(function(){
    console.log(3);
})複製代碼

在瀏覽器中會輸出 1,2,promise,3

而用node運行則會輸出 1,2,3,promise


在node中執行到相應的任務隊列時,會把任務隊列清空,裏面的任務依次放到執行棧中執行,而後在去執行下一隊列。


未完待續

若有錯誤,歡迎指正。圖片均來自網絡,侵刪

相關文章
相關標籤/搜索