更新時間:2021-06-17 來源:黑馬程序員 瀏覽量:
JavaScript的定時器可以完成一些異步操作。例如,同時設置多個定時器,每個定時器都在3秒后執(zhí)行一段代碼,則3秒后,這些定時器中的代碼都會執(zhí)行。JavaScript的定時器雖然沒有Java中的多線程那樣強大,但在開發(fā)中也能滿足大部分的需求。下面針對JavaSeript的執(zhí)行機制進行講解。
1、單線程
JavaScript語言的一大特點就是單線程,也就是說,同-一個時間只能做一件事。這是因為JavaScript這門腳本語言誕生的使命所致,即JavaScript是為處理頁面中用戶的交互,以及操作DOM而誕生的。比如,對某個DOM元素進行添加和刪除操作,不能同時進行,應該先進行添加,之后再刪除。
單線程就意味著,所有任務需要排隊,前一個任務結束,才會執(zhí)行后一個任務,這樣所導致的問題是,如果JavaScript執(zhí)行的時間過長,就會造成頁面的渲染不連貫,導致頁面渲染加載有阻塞的感覺。 為了更好地理解,下面我們通過段代碼來演示。
console.log(1); setTimeout(function () { console.log(3); }, 5000); console.log(2);
執(zhí)行上述代碼,在控制臺會看到程序先輸出了1、2,等待5秒后輸出3。由此可見,當調用setTimeout()方法后,該方法會立即執(zhí)行完成,然后執(zhí)行后面的代碼,在控制臺中輸出2。而為setTimeout()傳入的函數(shù),它會在5秒后執(zhí)行。像這樣的操作就稱為異步操作。這個異步執(zhí)行的函數(shù)稱為回調函數(shù),它的調用時機是由定時器來決定的。
2、同步和異步
為了更好地利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript腳本創(chuàng)建多個線程。于是JavaScript出現(xiàn)了同步和異步的概念。
所謂同步,就是前一個任務結束后再執(zhí)行后一個任務,程序的執(zhí)行順序與任務的排列順序是一致的、同步的。比如做飯的同步做法,燒水煮飯,等水開了之后,再去切菜,炒菜。
所謂異步,就是在做一件事件的同時,可以去處理其他的事情。還以做飯為例,異步做法是,在燒水煮飯的同時去切菜炒菜。 同步任務都是在主線程上執(zhí)行的,會形成一個執(zhí)行棧,而異步任務是通過回調函數(shù)實現(xiàn)的。一般來說,異步任務有3種類型,第1種是普通事件,如click、resize 等;第2種是資源加載,如load、error等;第3種是定時器,如setInterval()、setTimeout()。
3、執(zhí)行機制
當定時器的時間設為0的時候,就會產生一個問題, 到底是為定時器傳入的回調函數(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。顯然,為定時器傳入的回調函數(shù)是最后執(zhí)行的。為了降低偶然性,第5 ~ 7行的代碼拖慢了執(zhí)行時間,但最終結果仍然是3最后輸出。 在JavaScript中,同步任務是優(yōu)先執(zhí)行的,它們會被放入執(zhí)行棧中執(zhí)行,而異步任務(回調函數(shù))則被放人任務隊列中,如下圖所示。
在上圖中,一且執(zhí)行棧中的所有同步任務執(zhí)行完畢,系統(tǒng)就會按次序讀取任務隊列中的異步任務,于是被讀取的異步任務就會結束等待狀態(tài),進入執(zhí)行棧,開始執(zhí)行。因為JavaScript的主線程會不斷地重復獲得任務、執(zhí)行任務、再獲取任務、再執(zhí)行,所以這種機制被稱為事件循環(huán)( Event Loop )。
猜你喜歡:
javascript創(chuàng)建對象的幾種方式介紹?/a>