[深刻01] 執行上下文
[深刻02] 原型鏈
[深刻03] 繼承
[深刻04] 事件循環
[深刻05] 柯里化 偏函數 函數記憶
[深刻06] 隱式轉換 和 運算符
[深刻07] 瀏覽器緩存機制(http緩存機制)
[深刻08] 前端安全
[深刻09] 深淺拷貝
[深刻10] Debounce Throttle
[深刻11] 前端路由
[深刻12] 前端模塊化
[深刻13] 觀察者模式 發佈訂閱模式 雙向數據綁定
[深刻14] canvas
[深刻15] webSocket
[深刻16] webpack
[深刻17] http 和 https
[深刻18] CSS-interview
[react] Hookshtml
[部署01] Nginx
[部署02] Docker 部署vue項目
[部署03] gitlab-CI前端
[源碼-webpack01-前置知識] AST抽象語法樹
[源碼-webpack02-前置知識] Tapable
[源碼-webpack03] 手寫webpack - compiler簡單編譯流程vue
設計js的目的是爲了操做DOM等,若是是多線程,兩個線程同時對同一個DOM元素執行了不一樣的操做,就會形成( 爭奪執行權 )的問題
同步任務:在主線程上排隊執行的任務,只有前一個任務執行完畢,纔會執行後面的任務 |
異步任務:未進入主線程,而進入任務隊列的任務,只有"任務隊列"通知主線程,某個異步任務能夠執行了,而且主線程的同步任務執行完畢後,該任務纔會進入主線程執行 |
window.setTimeout(function() {
console.log('timer')
}, 100)
// setTimeout(callback, delay)會當即執行
// setTimeout的一個參數會在dalay毫秒後執行,前提是同步任務執行的時間要小於delay毫秒
// setTimeout()執行時,進入函數調用棧,或者叫執行上下文棧,執行完畢後,出棧
// 而callback回調會在delay毫秒後進入任務隊列,等待進入主線程
// 任務隊列:分爲macro-task,micro-task
indow.setTimeout(function() {
console.log('timer')
}, 0)
// setTimeout()的第二個參數是0,表示在執行完全部同步任務後,第一時間執行回調
// 關於setTimeout,即使主線程爲空,0毫秒實際上也是達不到的。根據HTML的標準,最低是4毫秒
複製代碼
// 注意:函數分爲初始化函數和回調函數,這樣區分只是爲了更好的理解事件循環而已
setTimeout(cb, delay)
// setTimeout()進入函數調用棧執行完後,出棧
// cb和dalay進入瀏覽器的分線程,被瀏覽器的定時器管理模塊執行,在delay時間後,將回調函數放入任務隊列中
// 有時候setTimeout()並不會在設置的時間後執行,是由於同步任務的執行超過了定時器指定的時間,
// 由於任務隊列的任務只有在主線程上的全部同步任務都執行完後(即調用棧中只剩全局上下文時),纔會執行
複製代碼
<script>
console.log('1');
function fn1() {
console.log('2');
}
fn1();
setTimeout(() => { // macro-task任務
console.log('3');
}, 0)
setTimeout(() => {
console.log('4')
}, 1000)
new Promise((resolve) => { // micro-task
console.log('5'); // 同步任務,同步任務按調用順序依次執行
return resolve()
}).then(res => console.log('6')) // micro-task先執行
</script>
執行結果:1 2 5 6 3 4
複製代碼
<script>
// 定時器A
setTimeout(() => {
console.log('1')
// 定時器B
setTimeout(() => console.log('2'), 0)
// a promise
Promise.resolve().then(() => console.log('3'))
}, 0)
// b promise
new Promise(resolve => {
console.log('4')
// 定時器C
setTimeout(() => {
console.log('5')
return resolve()
}, 0)
}).then(() => console.log('6'))
// 第一次Event loop
// 宏任務 A
// 微任務 b
// 過程:執行宏任務script總體代碼,執行完同步任務,清空micro-task,===> 輸出4,宏任務隊列:C A
// 第二次Event loop
// 宏任務 C A
// 微任務
// 過程:執行A, 宏任務:B C; 微任務:a; 清空micro-task, ===> 輸出 1 3,宏任務隊列: B C
// 第三次Event loop
// 宏任務 B C
// 微任務
// 過程:執行C, 清空micro-task, ===> 輸出 5 6, 宏任務隊列: B
// 第四次Event loop
// 宏任務:B
// 微任務
// 過程: 執行B,清空micro-task, ===> 輸出 2
// 結果: 4 1 3 5 6 2
</script>
複製代碼
示例3 - 鞏固學習html5
<script>
// A 定時器
setTimeout(() => {
console.log('1');
// b promise
Promise.resolve().then(() => console.log('2'))
}, 0);
// B promise
Promise.resolve().then(() => {
console.log('3');
// a定時器
setTimeout(() => console.log('4'), 0)
})
// 第一次Event loop
// 執行棧 window
// 宏任務 A
// 微任務 B
// 過程:執行宏任務script,清空micro-task, 輸出 3,並把 a定時器加入 宏任務隊列 a A
// 第二次Event loop
// 宏任務 a A
// 微任務 b
// 過程:執行宏任務A, 添加微任務 b, 清空微任務 b
// 第三次Event loop
// 宏任務 a
// 微任務
// 過程:執行宏任務a
// 結果:3 1 2 4
</script>
複製代碼
node事件循環機制
1. timers階段
- timers階段也叫定時器階段,主要是計時和執行到點的計時器
2. pending callbacks階段
- 系統相關,如tcp錯誤
3. idea prepare
- 準備工做
4. poll階段(輪詢隊列)// poll是輪詢的意思
(1) 若是輪詢隊列不爲空:依次從輪詢隊列中取出回調函數並執行,直到輪詢隊列爲空或者達到系統的最大限制
(2) 若是輪詢隊列爲空:
- 若是以前設置過setImmediate函數:直接進入下一個階段check階段
- 若是以前沒有設置過setImmedidate函數:在當前poll階段等待
- 直到輪詢隊列添加回調函數,就會4(1)的狀況執行
- 若是定時器到點了,也會去下一階段check階段
5. check階段
- 執行setImmediate函數
6. close callbacks 階段
- 執行close事件回調函數
注意:process.nextTick()能在任意階段優先執行
複製代碼
nodejs事件循環
setImmediate(() => {
console.log('setImmediate')
}) // 在poll階段,輪詢隊列爲空時,若是以前設置過setImmediate則直接跳到下一階段check階段就執行Immediate函數
setTimeout(() => console.log('setTimeout'), 0) // 第一個階段timer階段,計時器delay是0,則在第一個階段就執行
process.nextTick(() => console.log('process.nextTick')) // 任意階段優先執行
執行結果:
'process.nextTick'
'setTimeout'
'setImmediate'
複製代碼
[深刻01] 執行上下文
[深刻02] 原型鏈
[深刻03] 繼承node
yangbo5207.github.io/wutongluo/j…
juejin.im/post/5aacd1…
個人語雀:www.yuque.com/woowwu/msyq…react