首頁技術(shù)文章正文

JavaScript執(zhí)行機(jī)制詳細(xì)介紹

更新時間:2021-06-17 來源:黑馬程序員 瀏覽量:

IT培訓(xùn)班

JavaScript的定時器可以完成一些異步操作。例如,同時設(shè)置多個定時器,每個定時器都在3秒后執(zhí)行一段代碼,則3秒后,這些定時器中的代碼都會執(zhí)行。JavaScript的定時器雖然沒有Java中的多線程那樣強(qiáng)大,但在開發(fā)中也能滿足大部分的需求。下面針對JavaSeript的執(zhí)行機(jī)制進(jìn)行講解。


1、單線程

JavaScript語言的一大特點就是單線程,也就是說,同-一個時間只能做一件事。這是因為JavaScript這門腳本語言誕生的使命所致,即JavaScript是為處理頁面中用戶的交互,以及操作DOM而誕生的。比如,對某個DOM元素進(jìn)行添加和刪除操作,不能同時進(jìn)行,應(yīng)該先進(jìn)行添加,之后再刪除。

單線程就意味著,所有任務(wù)需要排隊,前一個任務(wù)結(jié)束,才會執(zhí)行后一個任務(wù),這樣所導(dǎo)致的問題是,如果JavaScript執(zhí)行的時間過長,就會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載有阻塞的感覺。 為了更好地理解,下面我們通過段代碼來演示。

console.log(1);
setTimeout(function () {
    console.log(3);
}, 5000);
console.log(2);

執(zhí)行上述代碼,在控制臺會看到程序先輸出了1、2,等待5秒后輸出3。由此可見,當(dāng)調(diào)用setTimeout()方法后,該方法會立即執(zhí)行完成,然后執(zhí)行后面的代碼,在控制臺中輸出2。而為setTimeout()傳入的函數(shù),它會在5秒后執(zhí)行。像這樣的操作就稱為異步操作。這個異步執(zhí)行的函數(shù)稱為回調(diào)函數(shù),它的調(diào)用時機(jī)是由定時器來決定的。


2、同步和異步

為了更好地利用多核CPU的計算能力,HTML5提出Web Worker標(biāo)準(zhǔn),允許JavaScript腳本創(chuàng)建多個線程。于是JavaScript出現(xiàn)了同步和異步的概念。

所謂同步,就是前一個任務(wù)結(jié)束后再執(zhí)行后一個任務(wù),程序的執(zhí)行順序與任務(wù)的排列順序是一致的、同步的。比如做飯的同步做法,燒水煮飯,等水開了之后,再去切菜,炒菜。

所謂異步,就是在做一件事件的同時,可以去處理其他的事情。還以做飯為例,異步做法是,在燒水煮飯的同時去切菜炒菜。 同步任務(wù)都是在主線程上執(zhí)行的,會形成一個執(zhí)行棧,而異步任務(wù)是通過回調(diào)函數(shù)實現(xiàn)的。一般來說,異步任務(wù)有3種類型,第1種是普通事件,如click、resize 等;第2種是資源加載,如load、error等;第3種是定時器,如setInterval()、setTimeout()。


3、執(zhí)行機(jī)制

當(dāng)定時器的時間設(shè)為0的時候,就會產(chǎn)生一個問題, 到底是為定時器傳入的回調(diào)函數(shù)優(yōu)先執(zhí)行,還是setTimeout()后面的代碼優(yōu)先執(zhí)行呢?示例代碼如下。

console.log(1);
setTimeout (function () {
    console.log(3);
    }, 0);
for (var i = 0, str = ''; i< 900000; i++) {
    str += i;
    //利用字符串拼接運算拖慢執(zhí)行時間
}
console.log(2);

上述代碼執(zhí)行后,輸出順序為1、2、3。顯然,為定時器傳入的回調(diào)函數(shù)是最后執(zhí)行的。為了降低偶然性,第5 ~ 7行的代碼拖慢了執(zhí)行時間,但最終結(jié)果仍然是3最后輸出。 在JavaScript中,同步任務(wù)是優(yōu)先執(zhí)行的,它們會被放入執(zhí)行棧中執(zhí)行,而異步任務(wù)(回調(diào)函數(shù))則被放人任務(wù)隊列中,如下圖所示。

1623910250277_javascript執(zhí)行機(jī)制.png

在上圖中,一且執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會按次序讀取任務(wù)隊列中的異步任務(wù),于是被讀取的異步任務(wù)就會結(jié)束等待狀態(tài),進(jìn)入執(zhí)行棧,開始執(zhí)行。因為JavaScript的主線程會不斷地重復(fù)獲得任務(wù)、執(zhí)行任務(wù)、再獲取任務(wù)、再執(zhí)行,所以這種機(jī)制被稱為事件循環(huán)( Event Loop )。



猜你喜歡:

javascript創(chuàng)建對象的幾種方式介紹?/a>

JavaScript數(shù)據(jù)類型:javascript數(shù)據(jù)類型有哪些?

什么是變量?JavaScript變量命名規(guī)范介紹

JavaScript中如何搜索數(shù)組元素?

黑馬程序員HTML&JS+前端培訓(xùn)課程

分享到:
在線咨詢 我要報名
和我們在線交談!