æµè§å¨ä¸ JavaScript çæ§è¡æµç¨å Node.js ä¸çæµç¨é½æ¯åºäº äºä»¶å¾ªç¯ çã
çè§£äºä»¶å¾ªç¯ç工使¹å¼å¯¹äºä»£ç ä¼åå¾éè¦ï¼ææ¶å¯¹äºæ£ç¡®çæ¶æä¹å¾éè¦ã
卿¬ç« ä¸ï¼æä»¬é¦å ä»ç»äºä»¶å¾ªç¯å·¥ä½æ¹å¼çç论ç»èï¼ç¶åä»ç»è¯¥ç¥è¯çå®é åºç¨ã
äºä»¶å¾ªç¯
äºä»¶å¾ªç¯ çæ¦å¿µé常ç®åã宿¯ä¸ä¸ªå¨ JavaScript 弿çå¾ ä»»å¡ï¼æ§è¡ä»»å¡åè¿å ¥ä¼ç ç¶æçå¾ æ´å¤ä»»å¡è¿å ä¸ªç¶æä¹é´è½¬æ¢çæ é循ç¯ã
弿çä¸è¬ç®æ³ï¼
- 彿任塿¶ï¼
- 仿å è¿å ¥çä»»å¡å¼å§æ§è¡ã
- ä¼ç ç´å°åºç°ä»»å¡ï¼ç¶å转å°ç¬¬ 1 æ¥ã
彿们æµè§ä¸ä¸ªç½é¡µæ¶å°±æ¯ä¸è¿°è¿ç§å½¢å¼ãJavaScript 弿大夿°æ¶å䏿§è¡ä»»ä½æä½ï¼å®ä» å¨èæ¬/å¤çç¨åº/äºä»¶æ¿æ´»æ¶æ§è¡ã
ä»»å¡ç¤ºä¾ï¼
- å½å¤é¨èæ¬
<script src="...">å è½½å®ææ¶ï¼ä»»å¡å°±æ¯æ§è¡å®ã - å½ç¨æ·ç§»å¨é¼ æ æ¶ï¼ä»»å¡å°±æ¯æ´¾çåº
mousemoveäºä»¶åæ§è¡å¤çç¨åºã - å½å®æçï¼scheduledï¼
setTimeoutæ¶é´å°è¾¾æ¶ï¼ä»»å¡å°±æ¯æ§è¡å ¶åè°ã - â¦â¦è¯¸å¦æ¤ç±»ã
è®¾ç½®ä»»å¡ ââ 弿å¤çå®ä»¬ ââ ç¶åçå¾ æ´å¤ä»»å¡ï¼å³ä¼ç ï¼å ä¹ä¸æ¶è CPU èµæºï¼ã
ä¸ä¸ªä»»å¡å°æ¥æ¶ï¼å¼æå¯è½æ£å¤äºç¹å¿ç¶æï¼é£ä¹è¿ä¸ªä»»å¡å°±ä¼è¢«æå ¥éåã
å¤ä¸ªä»»å¡ç»æäºä¸ä¸ªéåï¼å³æè°çâå®ä»»å¡éåâï¼v8 æ¯è¯ï¼ï¼
ä¾å¦ï¼å½å¼ææ£å¨å¿äºæ§è¡ä¸æ®µ script æ¶ï¼ç¨æ·å¯è½ä¼ç§»å¨é¼ æ è产ç mousemove äºä»¶ï¼setTimeout æè®¸ä¹å好尿ï¼ä»¥åå
¶ä»ä»»å¡ï¼è¿äºä»»å¡ç»æäºä¸ä¸ªéåï¼å¦ä¸å¾æç¤ºã
éåä¸çä»»å¡åºäºâå
è¿å
åºâçååæ§è¡ã彿µè§å¨å¼ææ§è¡å® script åï¼å®ä¼å¤ç mousemove äºä»¶ï¼ç¶åå¤ç setTimeout å¤çç¨åºï¼ä¾æ¤ç±»æ¨ã
å°ç®å为æ¢ï¼å¾ç®åï¼å¯¹å§ï¼
两个ç»èï¼
- 弿æ§è¡ä»»å¡æ¶æ°¸è¿ä¸ä¼è¿è¡æ¸²æï¼renderï¼ã妿任塿§è¡éè¦å¾é¿ä¸æ®µæ¶é´ä¹æ²¡å ³ç³»ãä» å¨ä»»å¡å®æåæä¼ç»å¶å¯¹ DOM çæ´æ¹ã
- 妿ä¸é¡¹ä»»å¡æ§è¡è±è´¹çæ¶é´è¿é¿ï¼æµè§å¨å°æ æ³æ§è¡å ¶ä»ä»»å¡ï¼ä¾å¦å¤çç¨æ·äºä»¶ãå æ¤ï¼å¨ä¸å®æ¶é´åï¼æµè§å¨ä¼æåºä¸ä¸ªå¦â页颿ªååºâä¹ç±»çè¦æ¥ï¼å»ºè®®ä½ ç»æ¢è¿ä¸ªä»»å¡ãè¿ç§æ åµå¸¸åç卿大é夿çè®¡ç®æå¯¼è´æ»å¾ªç¯çç¨åºé误æ¶ã
以䏿¯ç论ç¥è¯ãç°å¨ï¼è®©æä»¬æ¥ççå¦ä½åºç¨è¿äºç¥è¯ã
ç¨ä¾ 1ï¼æå CPU è¿è½½ä»»å¡
å设æä»¬æä¸ä¸ª CPU è¿è½½ä»»å¡ã
ä¾å¦ï¼è¯æ³é«äº®ï¼ç¨æ¥ç»æ¬é¡µé¢ä¸ç示ä¾ä»£ç çè²ï¼æ¯ç¸å½èè´¹ CPU èµæºçä»»å¡ã为äºé«äº®æ¾ç¤ºä»£ç ï¼å®æ§è¡åæï¼å建å¾å¤çäºè²çå ç´ ï¼ç¶åå°å®ä»¬æ·»å å°ææ¡£ä¸ ââ å¯¹äºææ¬éå¤§çææ¡£æ¥è¯´ï¼éè¦èè´¹å¾é¿æ¶é´ã
å½å¼æå¿äºè¯æ³é«äº®æ¶ï¼å®å°±æ æ³å¤çå ¶ä» DOM ç¸å ³çå·¥ä½ï¼ä¾å¦å¤çç¨æ·äºä»¶çãå®çè³å¯è½ä¼å¯¼è´æµè§å¨â䏿ï¼hiccupï¼âçè³âæèµ·ï¼hangï¼â䏿®µæ¶é´ï¼è¿æ¯ä¸å¯æ¥åçã
æä»¬å¯ä»¥éè¿å°å¤§ä»»å¡æåæå¤ä¸ªå°ä»»å¡æ¥é¿å
è¿ä¸ªé®é¢ãé«äº®æ¾ç¤ºå 100 è¡ï¼ç¶åä½¿ç¨ setTimeoutï¼å»¶æ¶åæ°ä¸º 0ï¼æ¥å®æï¼scheduleï¼å 100 è¡çé«äº®æ¾ç¤ºï¼ä¾æ¤ç±»æ¨ã
ä¸ºäºæ¼ç¤ºè¿ç§æ¹æ³ï¼ç®åèµ·è§ï¼è®©æä»¬åä¸ä¸ªä» 1 æ°å° 1000000000 ç彿°ï¼èä¸åææ¬é«äº®ã
å¦æä½ è¿è¡ä¸é¢è¿æ®µä»£ç ï¼ä½ ä¼çå°å¼æä¼âæèµ·â䏿®µæ¶é´ãå¯¹äºæå¡ç«¯ JS æ¥è¯´è¿æ¾èæè§ï¼å¹¶ä¸å¦æä½ 卿µè§å¨ä¸è¿è¡å®ï¼å°è¯ç¹å»é¡µé¢ä¸å ¶ä»æé®æ¶ï¼ä½ ä¼åç°å¨è®¡æ°ç»æä¹åä¸ä¼å¤çå ¶ä»äºä»¶ã
let i = 0;
let start = Date.now();
function count() {
// åä¸ä¸ªç¹éçä»»å¡
for (let j = 0; j < 1e9; j++) {
i++;
}
alert("Done in " + (Date.now() - start) + 'ms');
}
count();
æµè§å¨çè³å¯è½ä¼æ¾ç¤ºä¸ä¸ªâèæ¬æ§è¡æ¶é´è¿é¿âçè¦åã
让æä»¬ä½¿ç¨åµå¥ç setTimeout è°ç¨æ¥æåè¿ä¸ªä»»å¡ï¼
let i = 0;
let start = Date.now();
function count() {
// åç¹éçä»»å¡çä¸é¨å (*)
do {
i++;
} while (i % 1e6 != 0);
if (i == 1e9) {
alert("Done in " + (Date.now() - start) + 'ms');
} else {
setTimeout(count); // 宿ï¼scheduleï¼æ°çè°ç¨ (**)
}
}
count();
ç°å¨ï¼æµè§å¨çé¢å¨â计æ°âè¿ç¨ä¸å¯ä»¥æ£å¸¸ä½¿ç¨ã
忬¡æ§è¡ count ä¼å®æå·¥ä½ (*) çä¸é¨åï¼ç¶åæ ¹æ®éè¦éæ°å®æï¼scheduleï¼èªèº«çæ§è¡ (**)ï¼
- é¦å
æ§è¡è®¡æ°ï¼
i=1...1000000ã - ç¶åæ§è¡è®¡æ°ï¼
i=1000001..2000000ã - â¦â¦ä»¥æ¤ç±»æ¨ã
ç°å¨ï¼å¦æå¨å¼æå¿äºæ§è¡ç¬¬ä¸é¨åæ¶åºç°äºä¸ä¸ªæ°çå¯ä»»å¡ï¼ä¾å¦ onclick äºä»¶ï¼ï¼å该任å¡ä¼è¢«æå
¥éåï¼ç¶åå¨ç¬¬ä¸é¨åæ§è¡ç»ææ¶ï¼å¹¶å¨ä¸ä¸é¨åå¼å§æ§è¡åï¼ä¼æ§è¡è¯¥å¯ä»»å¡ã卿æ§å°å¨ä¸¤æ¬¡ count æ§è¡æé´è¿åäºä»¶å¾ªç¯ï¼è¿ä¸º JavaScript 弿æä¾äºè¶³å¤çâ空æ°âæ¥æ§è¡å
¶ä»æä½ï¼ä»¥ååºå
¶ä»çç¨æ·è¡ä¸ºã
å¼å¾æ³¨æçæ¯è¿ä¸¤ç§åä½ ââ æ¯å¦ä½¿ç¨äº setTimeout 对任å¡è¿è¡æå ââ 卿§è¡éåº¦ä¸æ¯ç¸å½çã卿§è¡è®¡æ°çæ»èæ¶ä¸æ²¡æå¤å°å·®å¼ã
为äºä½¿ä¸¤è èæ¶æ´æ¥è¿ï¼è®©æä»¬æ¥åä¸ä¸ªæ¹è¿ã
æä»¬å°è¦æè°åº¦ï¼schedulingï¼ç§»å¨å° count() çå¼å¤´ï¼
let i = 0;
let start = Date.now();
function count() {
// å°è°åº¦ï¼schedulingï¼ç§»å¨å°å¼å¤´
if (i < 1e9 - 1e6) {
setTimeout(count); // 宿ï¼scheduleï¼æ°çè°ç¨
}
do {
i++;
} while (i % 1e6 != 0);
if (i == 1e9) {
alert("Done in " + (Date.now() - start) + 'ms');
}
}
count();
ç°å¨ï¼å½æä»¬å¼å§è°ç¨ count() æ¶ï¼ä¼ç尿们éè¦å¯¹ count() è¿è¡æ´å¤è°ç¨ï¼æä»¬å°±ä¼å¨å·¥ä½åç«å³å®æï¼scheduleï¼å®ã
å¦æä½ è¿è¡å®ï¼ä½ å¾å®¹ææ³¨æå°å®è±è´¹çæ¶é´ææ¾åå°äºã
为ä»ä¹ï¼
è¿å¾ç®åï¼ä½ åºè¯¥è¿è®°å¾ï¼å¤ä¸ªåµå¥ç setTimeout è°ç¨å¨æµè§å¨ä¸çæå°å»¶è¿ä¸º 4msãå³ä½¿æä»¬è®¾ç½®äº 0ï¼ä½è¿æ¯ 4msï¼æè
æ´ä¹
ä¸äºï¼ãæä»¥æä»¬å®æï¼scheduleï¼å¾è¶æ©ï¼è¿è¡é度ä¹å°±è¶å¿«ã
æåï¼æä»¬å°ä¸ä¸ªç¹éç任塿åæäºå é¨åï¼ç°å¨å®ä¸ä¼é»å¡ç¨æ·çé¢äºãèä¸å ¶æ»èæ¶å¹¶ä¸ä¼é¿å¾å¤ã
ç¨ä¾ 2ï¼è¿åº¦æç¤º
对æµè§å¨èæ¬ä¸çè¿è½½åä»»å¡è¿è¡æåçå¦ä¸ä¸ªå¥½å¤æ¯ï¼æä»¬å¯ä»¥æ¾ç¤ºè¿åº¦æç¤ºã
æ£å¦å颿æå°çï¼ä» å¨å½åè¿è¡çä»»å¡å®æåï¼æä¼å¯¹ DOM ä¸çæ´æ¹è¿è¡ç»å¶ï¼æ 论è¿ä¸ªä»»å¡è¿è¡è±è´¹äºå¤é¿æ¶é´ã
ä»ä¸æ¹é¢è®²ï¼è¿é常好ï¼å 为æä»¬ç彿°å¯è½ä¼å建å¾å¤å ç´ ï¼å°å®ä»¬ä¸ä¸ªæ¥ä¸ä¸ªå°æå ¥å°ææ¡£ä¸ï¼å¹¶æ´æ¹å ¶æ ·å¼ ââ 访é®è ä¸ä¼çå°ä»»ä½æªå®æçâä¸é´æâå 容ãå¾éè¦ï¼å¯¹å§ï¼
è¿æ¯ä¸ä¸ªç¤ºä¾ï¼å¯¹ i çæ´æ¹å¨è¯¥å½æ°å®æåä¸ä¼æ¾ç¤ºåºæ¥ï¼æä»¥æä»¬å°åªä¼çå°æåçå¼ï¼
<div id="progress"></div>
<script>
function count() {
for (let i = 0; i < 1e6; i++) {
i++;
progress.innerHTML = i;
}
}
count();
</script>
â¦â¦ä½æ¯æä»¬ä¹å¯è½æ³å¨ä»»å¡æ§è¡æé´å±ç¤ºä¸äºä¸è¥¿ï¼ä¾å¦è¿åº¦æ¡ã
妿æä»¬ä½¿ç¨ setTimeout å°ç¹éç任塿åæå é¨åï¼é£ä¹ååå°±ä¼è¢«å¨å®ä»¬ä¹é´ç»å¶åºæ¥ã
è¿çèµ·æ¥æ´å¥½çï¼
<div id="progress"></div>
<script>
let i = 0;
function count() {
// åç¹éçä»»å¡çä¸é¨å (*)
do {
i++;
progress.innerHTML = i;
} while (i % 1e3 != 0);
if (i < 1e7) {
setTimeout(count);
}
}
count();
</script>
ç°å¨ div æ¾ç¤ºäº i çå¼çå¢é¿ï¼è¿å°±æ¯è¿åº¦æ¡çä¸ç§ã
ç¨ä¾ 3ï¼å¨äºä»¶ä¹ååä¸äºäºæ
å¨äºä»¶å¤çç¨åºä¸ï¼æä»¬å¯è½ä¼å³å®æ¨è¿æäºè¡ä¸ºï¼ç´å°äºä»¶åæ³¡å¹¶å¨ææçº§å«ä¸å¾å°å¤çåãæä»¬å¯ä»¥éè¿å°è¯¥ä»£ç å
è£
å°é¶å»¶è¿ç setTimeout 䏿¥åå°è¿ä¸ç¹ã
å¨ å建èªå®ä¹äºä»¶ ä¸ç« ä¸ï¼æä»¬çå°è¿è¿æ ·ä¸ä¸ªä¾åï¼èªå®ä¹äºä»¶ menu-open è¢«å¨ setTimeout ä¸åæ´¾ï¼dispatchedï¼ï¼æä»¥å®å¨ click äºä»¶è¢«å¤ç宿ä¹ååçã
menu.onclick = function() {
// ...
// å建ä¸ä¸ªå
·æè¢«ç¹å»çèåé¡¹çæ°æ®çèªå®ä¹äºä»¶
let customEvent = new CustomEvent("menu-open", {
bubbles: true
});
// 弿¥åæ´¾ï¼dispatchï¼èªå®ä¹äºä»¶
setTimeout(() => menu.dispatchEvent(customEvent));
};
å®ä»»å¡å微任å¡
é¤äºæ¬ç« ä¸æè®²ç å®ä»»å¡ï¼macrotaskï¼ å¤ï¼è¿æå¨ 微任å¡ï¼Microtaskï¼ ä¸ç« 䏿å°ç 微任å¡ï¼microtaskï¼ã
微任å¡ä»
æ¥èªäºæä»¬ç代ç ãå®ä»¬é常æ¯ç± promise å建çï¼å¯¹ .then/catch/finally å¤çç¨åºçæ§è¡ä¼æä¸ºå¾®ä»»å¡ã微任å¡ä¹è¢«ç¨äº await çâå¹åâï¼å ä¸ºå®æ¯ promise å¤ççå¦ä¸ç§å½¢å¼ã
è¿æä¸ä¸ªç¹æ®ç彿° queueMicrotask(func)ï¼å®å¯¹ func è¿è¡æéï¼ä»¥å¨å¾®ä»»å¡éå䏿§è¡ã
æ¯ä¸ªå®ä»»å¡ä¹åï¼å¼æä¼ç«å³æ§è¡å¾®ä»»å¡éåä¸çææä»»å¡ï¼ç¶ååæ§è¡å ¶ä»çå®ä»»å¡ï¼ææ¸²æï¼æè¿è¡å ¶ä»ä»»ä½æä½ã
ä¾å¦ï¼ççä¸é¢è¿ä¸ªç¤ºä¾ï¼
setTimeout(() => alert("timeout"));
Promise.resolve()
.then(() => alert("promise"));
alert("code");
è¿éçæ§è¡é¡ºåºæ¯ææ ·çï¼
codeé¦å æ¾ç¤ºï¼å ä¸ºå®æ¯å¸¸è§ç忥è°ç¨ãpromise第äºä¸ªåºç°ï¼å 为thenä¼éè¿å¾®ä»»å¡éåï¼å¹¶å¨å½å代ç ä¹åæ§è¡ãtimeoutæåæ¾ç¤ºï¼å ä¸ºå®æ¯ä¸ä¸ªå®ä»»å¡ã
æ´è¯¦ç»çäºä»¶å¾ªç¯å¾ç¤ºå¦ä¸ï¼é¡ºåºæ¯ä»ä¸å°ä¸ï¼å³ï¼é¦å æ¯èæ¬ï¼ç¶åæ¯å¾®ä»»å¡ï¼æ¸²æçï¼ï¼
微任å¡ä¼å¨æ§è¡ä»»ä½å ¶ä»äºä»¶å¤çï¼ææ¸²æï¼ææ§è¡ä»»ä½å ¶ä»å®ä»»å¡ä¹å宿ã
è¿å¾éè¦ï¼å 为å®ç¡®ä¿äºå¾®ä»»å¡ä¹é´çåºç¨ç¨åºç¯å¢åºæ¬ç¸åï¼æ²¡æé¼ æ åæ æ´æ¹ï¼æ²¡ææ°çç½ç»æ°æ®çï¼ã
妿æä»¬æ³è¦å¼æ¥æ§è¡ï¼å¨å½å代ç ä¹åï¼ä¸ä¸ªå½æ°ï¼ä½æ¯è¦å¨æ´æ¹è¢«æ¸²æææ°äºä»¶è¢«å¤çä¹åæ§è¡ï¼é£ä¹æä»¬å¯ä»¥ä½¿ç¨ queueMicrotask æ¥å¯¹å
¶è¿è¡å®æï¼scheduleï¼ã
è¿æ¯ä¸ä¸ªä¸åé¢é£ä¸ªä¾å类似çï¼å¸¦æâ计æ°è¿åº¦æ¡âç示ä¾ï¼ä½æ¯å®ä½¿ç¨äº queueMicrotask è䏿¯ setTimeoutãä½ å¯ä»¥çå°å®å¨æåææ¸²æãå°±ååçæ¯åæ¥ä»£ç 䏿 ·ï¼
<div id="progress"></div>
<script>
let i = 0;
function count() {
// åç¹éçä»»å¡çä¸é¨å (*)
do {
i++;
progress.innerHTML = i;
} while (i % 1e3 != 0);
if (i < 1e6) {
queueMicrotask(count);
}
}
count();
</script>
æ»ç»
æ´è¯¦ç»çäºä»¶å¾ªç¯ç®æ³ï¼å°½ç®¡ä¸ è§è ç¸æ¯ä»ç¶æ¯ç®åè¿çï¼ï¼
- ä» å®ä»»å¡ éåï¼ä¾å¦ âscriptâï¼ä¸åºéï¼dequeueï¼å¹¶æ§è¡ææ©çä»»å¡ã
- æ§è¡ææ 微任å¡ï¼
- å½å¾®ä»»å¡éåé空æ¶ï¼
- åºéï¼dequeueï¼å¹¶æ§è¡ææ©ç微任å¡ã
- å½å¾®ä»»å¡éåé空æ¶ï¼
- 妿æåæ´ï¼åå°åæ´æ¸²æåºæ¥ã
- 妿å®ä»»å¡éå为空ï¼åä¼ç ç´å°åºç°å®ä»»å¡ã
- è½¬å°æ¥éª¤ 1ã
宿ï¼scheduleï¼ä¸ä¸ªæ°ç å®ä»»å¡ï¼
- 使ç¨é¶å»¶è¿ç
setTimeout(f)ã
å®å¯è¢«ç¨äºå°ç¹éç计ç®ä»»å¡æåæå¤ä¸ªé¨åï¼ä»¥ä½¿æµè§å¨è½å¤å¯¹ç¨æ·äºä»¶ä½åºååºï¼å¹¶å¨ä»»å¡çåé¨åä¹é´æ¾ç¤ºä»»å¡è¿åº¦ã
æ¤å¤ï¼ä¹è¢«ç¨äºå¨äºä»¶å¤çç¨åºä¸ï¼å°ä¸ä¸ªè¡ä¸ºï¼actionï¼å®æï¼scheduleï¼å¨äºä»¶è¢«å®å ¨å¤çï¼åæ³¡å®æï¼åã
宿ä¸ä¸ªæ°ç 微任å¡ï¼
- 使ç¨
queueMicrotask(f)ã - promise å¤çç¨åºä¹ä¼éè¿å¾®ä»»å¡éåã
å¨å¾®ä»»å¡ä¹é´æ²¡æ UI æç½ç»äºä»¶çå¤çï¼å®ä»¬ä¸ä¸ªç«å³æ¥ä¸ä¸ªå°æ§è¡ã
æä»¥ï¼æä»¬å¯ä»¥ä½¿ç¨ queueMicrotask æ¥å¨ä¿æç¯å¢ç¶æä¸è´çæ
åµä¸ï¼å¼æ¥å°æ§è¡ä¸ä¸ªå½æ°ã
对äºä¸åºè¯¥é»å¡äºä»¶å¾ªç¯çèæ¶é¿çç¹é计ç®ä»»å¡ï¼æä»¬å¯ä»¥ä½¿ç¨ Web Workersã
è¿æ¯å¨å¦ä¸ä¸ªå¹¶è¡çº¿ç¨ä¸è¿è¡ä»£ç çæ¹å¼ã
Web Workers å¯ä»¥ä¸ä¸»çº¿ç¨äº¤æ¢æ¶æ¯ï¼ä½æ¯å®ä»¬å ·æèªå·±çåéåäºä»¶å¾ªç¯ã
Web Workers 没æè®¿é® DOM çæéï¼å æ¤ï¼å®ä»¬å¯¹äºåæ¶ä½¿ç¨å¤ä¸ª CPU å æ ¸ç计ç®é常æç¨ã
è¯è®º
<code>æ ç¾æå ¥åªæå 个è¯ç代ç ï¼æå ¥å¤è¡ä»£ç å¯ä»¥ä½¿ç¨<pre>æ ç¾ï¼å¯¹äºè¶ è¿ 10 è¡ç代ç ï¼å»ºè®®ä½ ä½¿ç¨æ²ç®±ï¼plnkrï¼JSBinï¼codepenâ¦ï¼