摘要:而之后事件循環一直會去遍歷任務隊列,一旦有任務放入就會放入主線程中執行。任務隊列所謂任務是返回的一個個通知,讓主線程在讀取任務隊列的時候得知這個異步任務已經完成,下一步該執行這個任務的回調函數了。
javascript單線程
瀏覽器端,復雜的UI環境會限制多線程語言的開發。棧
例如,一個線程在操作一個DOM元素時,另一個線程需要去刪除DOM元素,
這個之間就需要進行狀態的同步,何況前端可能不止操作這么一個DOM元素。
所以,為了避免在開發過程中,去進行復雜的同步,選用單線程語言進行開發是最好的解決方案
棧就是和列表類似的一種數據結構,它可以用來解決計算機世界里很多的問題。棧是一種高效的數據結構,因為數據只能在棧頂添加或刪除,所以這樣的操作很快,而且容易實現。
棧的使用遍布程序語言的方方面面,從表達式求值到處理函數調用; 函數調用形成了一個棧幀
具有一種后入先出(LIFO,last-in-first-out)的數據結構
由于棧具有后入先出的特點,所有任何不在棧頂的元素都無法訪問,為了拿到棧底的元素,必選先拿掉上面的元素
可在線演示這段代碼的執行流程
function fun1(){ return "hello hip-hop"; } function fun2(){ return fun1(); } function fun3(){ console.log(fun2()); } fun3(); //"hello hip-hop"堆(引用類型)
當我們在程序中創建一個對象時,這個對象將被保存到運行時數據區中,以便反復利用(因為對象的創建成本開銷較大),這個運行時數據區就是堆內存。隊列
堆內存中的對象不會隨方法的結束而銷毀,即使方法結束后,這個對象還可能被另一個引用變量所引用(方法的參數傳遞時很常見),則這個對象依然不會被銷毀,只有當一個對象沒有任何引用變量引用它時,
系統的垃圾回收機制才會在核實的時候回收它對象被分配在一個堆中,即用以表示一個大部分非結構化的內存區域
排隊在第一個的人先辦理業務,其它人只能排著,直到輪到他們為止只能在末尾插入元素,在隊首刪除元素。事件循環機制
隊列用于存儲按順序排列的數據先進先出列被用在很多地方。比如提交操作系統執行一系列進程。打印任務池等。一些仿真系統用來模擬銀行或雜貨店里排隊的顧客
這幅圖片中,我們可以看到完整的執行流程,其中涉及到的異步事件有DOM事件、ajax請求和setTimeout。所以,整體的執行流程是這樣子的:
所有同步任務會在主線程的調用棧中執行。
在主線程之外,還有一個任務隊列,一旦指定事件發生之后,異步任務就會被放入任務隊列中
當主線程執行完調用棧中的同步任務時,會遍歷任務隊列,將任務隊列中的任務放入主線程中執行。而之后事件循環一直會去遍歷任務隊列,一旦有任務放入就會放入主線程中執行。
這樣,我們就已經初步了解了同步和異步之間的實現,以及瀏覽器中的事件循環機制。
任務隊列所謂任務是WebAPIs返回的一個個通知,讓JS主線程在讀取任務隊列的時候得知這個異步任務已經完成,下一步該執行這個任務的回調函數了。
主線程擁有多個任務隊列,不同的任務隊列用來排列來自不同任務源的任務。
任務源是什么?像setTimeout/Promise/DOM事件等都是任務源,來自同類任務源的任務我們稱它們是同源的,比如setTimeout與setInterval就是同源的。
在ES6標準中任務隊列又分為宏觀任務隊列和微觀任務隊列
ES6標準中任務隊列存在兩種類型,一種就是上邊提到的一些隊列,
宏觀任務隊列(macrotask queue):setTimeout、網絡請求Ajax、用戶IO等,
微觀任務隊列(microtask queue),Promise就屬于微觀任務隊列
在執行棧執行的過程中會把屬于微觀任務隊列的任務分配到相應的微觀任務隊列中去。而在調用棧執行空之后,主線程讀取任務隊列時,會先讀取所有微觀任務隊列,然后讀取一個宏觀任務隊列,再讀取所有的微觀任務隊列
setTimeout(function(){console.log(4)},0); new Promise(function(resolve){ console.log(1) for( var i=0 ; i<10000 ; i++ ){ i==9999 && resolve() } console.log(2) }).then(function(){ console.log(5) }); console.log(3);
腳本開始執行,最先遇到setTimeout,交給瀏覽器去計時,達到setTimeout限制最短計時之后,把這個任務推入setTimeout隊列。
遇到Promise構造函數,構造函數參數執行,輸出1,調用resolve改變Promise對象的狀態,然后輸出2。
Promise對象調用then方法,將這個任務推入Promise任務隊列。
執行console.log(3),輸出3。
調用棧為空,讀取任務隊列,按照 讀取所有微觀任務隊列 -> 執行 ->
讀取一個宏觀任務隊列 -> 執行 ->
讀取所有微觀任務隊列 -> 執行 ->
再讀取一個宏觀任務隊列…的順序。
讀取所有微觀任務隊列中的任務,執行這些任務指定的回調函數。執行then指定的回調函數,輸出5(微觀任務隊列也具有優先級)。
最后讀取到setTimeout的任務,執行回調函數,輸出4。
所以最后的輸出順序是1,2,3,5,4,而不是1,2,3,4,5。如果不清楚微觀任務隊列的執行機制,很容易將兩個異步任務歸為一類,將執行順序判斷錯誤
零延遲零延遲并不是意味著回調會立即執行。 在零延遲調用 setTimeout 時,其并不是過了給定的時間間隔后就馬上執行回調函數。
其等待的時間基于隊列里正在等待的消息數量。 在下面的例子中,"this is just a message" 將會在回調
(callback) 獲得處理之前輸出到控制臺, 這是因為延遲是要求運行時 (runtime) 處理請求所需的最小時間,但不是有所保證的時間
(function () { console.log("this is the start"); setTimeout(function cb() { console.log("this is a msg from call back"); }); console.log("this is just a message"); setTimeout(function cb1() { console.log("this is a msg from call back1"); }, 0); console.log("this is the end"); })(); // "this is the start" // "this is just a message" // "this is the end" // "this is a msg from call back" // "this is a msg from call back1"
參考
《javascript高級程序設計》
https://developer.mozilla.org...
http://www.cnblogs.com/ahthw/...
https://kongchenglc.github.io...
https://github.com/laizimo/zi...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/110125.html
摘要:閉包能用來實現私有化和創建工廠函數等作用。關于閉包的常見面試題是這樣的寫一個函數,循環一個整數數組,延遲秒打印這個數組中每個元素的索引。 文章來源:http://mp.weixin.qq.com/s/vs0... 前言 在公眾號上看到了這篇文章,覺得很有用,有助于理解JS學習中的一些重點難點。決定把它整理下發布出來。該文章主要介紹了JS中的三個問題。在以后的幾篇文章里,我會詳細介紹這三...
摘要:支持三個參數分別表示事件名稱,是否可以冒泡,是否阻止事件的默認操作觸發參數表示事件對象,是方法返回的創建的對象監聽方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識點雖然是老生長談的,但對于我來說多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會長篇大論,只會挑重點;具體的小伙伴們自行查找) 什么是事件 在編程時系統內發生的動作或者發生...
摘要:支持三個參數分別表示事件名稱,是否可以冒泡,是否阻止事件的默認操作觸發參數表示事件對象,是方法返回的創建的對象監聽方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識點雖然是老生長談的,但對于我來說多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會長篇大論,只會挑重點;具體的小伙伴們自行查找) 什么是事件 在編程時系統內發生的動作或者發生...
摘要:支持三個參數分別表示事件名稱,是否可以冒泡,是否阻止事件的默認操作觸發參數表示事件對象,是方法返回的創建的對象監聽方法自定義事件常用模擬模擬方法操作或者自定義事件我的自定義事件。 事件這塊知識點雖然是老生長談的,但對于我來說多多整理,多多感悟,溫故知新,每次看看這塊都有不同的收獲.(在這里我不會長篇大論,只會挑重點;具體的小伙伴們自行查找) 什么是事件 在編程時系統內發生的動作或者發生...
閱讀 1876·2021-09-24 09:48
閱讀 3220·2021-08-26 14:14
閱讀 1674·2021-08-20 09:36
閱讀 1460·2019-08-30 15:55
閱讀 3628·2019-08-26 17:15
閱讀 1425·2019-08-26 12:09
閱讀 606·2019-08-26 11:59
閱讀 3323·2019-08-26 11:57