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

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

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

IT培訓(xùn)班

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


1、單線程

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

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

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

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


2、同步和異步

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

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

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


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

當(dāng)定時(shí)器的時(shí)間設(shè)為0的時(shí)候,就會(huì)產(chǎn)生一個(gè)問題, 到底是為定時(shí)器傳入的回調(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;
    //利用字符串拼接運(yùn)算拖慢執(zhí)行時(shí)間
}
console.log(2);

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

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

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



猜你喜歡:

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

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

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

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

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

分享到:
在線咨詢 我要報(bào)名
和我們?cè)诰€交談!