在javascript中,存在調用棧 (call stack)
和內存堆(memory heap)
,程序中函數依次進入棧中等待執行,若執行時遇到異步方法,該異步方法會被添加到用於回調的任務隊列(task queue)
中,【即JavaScript執行引擎的單線程擁有一個調用棧、內存堆和一個任務隊列】javascript
調用棧 (call stack):CallStack是用來處理函數調用與返回的。特色是先進後出,每次調用一個函數,Javascript運行時會生成一個新的調用結構壓入CallStack。而函數調用結束返回時,JavaScript運行時會將棧頂的調用結構彈出。因爲棧的LIFO特性,每次彈出的必然是最新調用的那個函數的結構。函數調用會造成了一個堆棧幀,存放基本數據類型的變量java
內存堆(memory head):引用數據類型被存放在堆中,在咱們進行淺複製時,咱們改變的只是引用數據類型在棧內存中的引用地址,實際上它在堆內存中的引用地址仍然沒有發生變化git
任務隊列(task queue):javaScript 運行時包含了一個待處理的任務隊列。github
javascript引擎是單線程的,它的併發模型基於Event Loop(事件循環)
算法
當線程中的同步任務執行完,
執行棧
爲空時,則從任務隊列(task queue)
中取出異步任務進行處理。這個處理過程包含了調用與這個任務相關聯的函數(以及於是建立了一個初始堆棧幀)。當執行棧
再次爲空的時候,也就意味着該任務處理結束,從任務隊列中取出下一個異步任務進行處理,不斷重複,這個過程是循環不斷的, 因此整個的這種運行機制又稱爲Event Loop(事件循環)
.promise
宏任務隊列
與微任務隊列
,setTimeout(()=>{
console.log('timer')
})
Promise.resolve('promise').then((res)=>{
console.log(res)
})
複製代碼
Promise.resolve('promise').then((res)=>{
console.log(res)
setTimeout(()=>{
console.log('timer')
})
})
複製代碼
Promise.resolve('promise1').then((res)=>{
console.log(res)
Promise.resolve('promise2').then((res)=>{
console.log(res)
Promise.resolve('promise3').then((res)=>{
console.log(res)
})
})
setTimeout(()=>{
console.log('timer')
})
})
複製代碼
Event loop 在瀏覽器端與NodeJS中的差異 以及 NodeJS中關於setTimeout與setImmediate引起的問題瀏覽器