您好,登錄后才能下訂單哦!
本篇內容主要講解“JS運行機制實例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“JS運行機制實例分析”吧!
1.為什么JS是單線程的?
JS的單線程,與它的用途有關。
作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。
比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節(jié)點上添加內容,另一個線程刪除了這個節(jié)點,這時瀏覽器應該以哪個線程為準
但是瀏覽器是多線程的
2.事件循環(huán)機制中的兩種任務
宏任務:整體代碼,setTimeout,setInterval等
微任務:new Promise ().then的回調,MutationObserver(前端回溯)用來監(jiān)聽事件的改變的
3.為什么要引入微任務的概念,只有宏任務不行嗎
宏任務遵循先進先出的原則執(zhí)行,但是如果在宏任務執(zhí)行的過程中有了優(yōu)先級更高的任務需要先執(zhí)行,那么此時往任務隊列中添加新任務的話,因為宏任務秉持著先進先出的原則,新添加的任務也只能是被排在后面的,那是萬萬不行的,所以才引入了微任務
4.事件循環(huán)
先執(zhí)行同步,再執(zhí)行異步,異步中先執(zhí)行微任務再執(zhí)行宏任務
首先,整體的js代碼(作為第一個宏任務)開始執(zhí)行的時候,會把所有代碼分為同步任務、異步任務兩部分,
同步任務會直接進入主線程依次執(zhí)行,同步任務執(zhí)行完后,執(zhí)行異步任務,
異步任務會再分為宏任務和微任務,
微任務中先執(zhí)行同步任務,異步任務依舊放到任務隊列中排隊,
當主線程空閑的時候,任務隊列中異步任務再依次執(zhí)行
上述過程會不斷重復,這就是Event Loop,比較完整的事件循環(huán)
5.Promise
new Promise(() => {}).then()
敲黑板劃重點——
前面的 new Promise() 這一部分是一個構造函數,這是一個同步任務
后面的 .then() 才是一個異步微任務
new Promise((resolve) => {
console.log(1)
resolve()
}).then(()=>{
console.log(2)
})
console.log(3)
//上面代碼輸出1 3 2
6.async / await
async/await本質上還是基于Promise的一些封裝,而Promise是屬于微任務的一種
所以在使用await關鍵字與Promise.then效果類似
setTimeout(() => console.log(4))
async function test() {
console.log(1)
await Promise.resolve()
console.log(3)
}
test()
console.log(2)
//上述代碼輸出1 2 3 4
setTimeout(() => console.log(4))
async function test() {
console.log(1)
await async2()
console.log(3)
}
function async2() {
console.log(5);
}
test()
console.log(2)
//上述代碼輸出1 5 2 3 4
await 修飾的函數及以前的代碼,相當于與 new Promise 的同步代碼
await 以后的代碼相當于 Promise.then的異步
7.附上幾道面試題
function test() {
console.log(1)
setTimeout(function () {
console.log(2)
}, 1000)
}
test();
setTimeout(function () {
console.log(3)
})
new Promise(function (resolve) {
console.log(4)
setTimeout(function () {
console.log(5)
}, 100)
resolve()
}).then(function () {
setTimeout(function () {
console.log(6)
}, 0)
console.log(7)
})
console.log(8)
//上述代碼輸出 1、4、8、7、3、6、5、2
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(() => {
console.log('setTimeout');
}, 0);
async1();
new Promise((resolve)=> {
console.log('promise1');
resolve()
}).then(()=> {
console.log('promise2');
})
console.log('script end');
//上述代碼輸出
// 'script start'
//'async1 start'
//'async2'
//'promise1'
//'script end'
//'async1 end'
//'promise2'
//'setTimeout'
//await async2();
//相當于 new Promise((resolve) => {
async2();
resolve();
}).then(() => { console.log('async1 end') })
console.log('start');
setTimeout(() => {
console.log('children2');
Promise.resolve().then(() => {
console.log('children3');
})
}, 0);
new Promise((resolve, reject) => {
console.log('children4');
setTimeout(() => {
console.log('children5');
resolve('children6')
}, 0);
}).then(res => {
console.log('children7');
setTimeout(() => {
console.log(res);
}, 0);
})
// 上述代碼輸出
//'start'
//'children4'
//第一輪宏任務結束,發(fā)現(xiàn)沒有微任務,原因:new Promise里并沒有resolve(),只有resolve()才會把.then放到微任務里
//'children2'
//'children3'
//'children5'
//'children7'
//'children6'
const p = function () {
return new Promise((resolve, reject) => {
const p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 0);
resolve(2)
})
p1.then(res => {
console.log(res);
})
console.log(3);
resolve(4)
})
}
p().then(res => {
console.log(res);
})
console.log('end');
// 上述代碼輸出
//3
//end
//Promise的狀態(tài)是唯一且不可改變的,所有當resolve(2)的時候.then已經被輸出了,setTimeout里的resolve(1)就沒有了
//2
//4
到此,相信大家對“JS運行機制實例分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續(xù)學習!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。