JavaScript 引擎是單線程運(yùn)行的假残,瀏覽器無論在什么時候都只且只有一個線程在運(yùn)行 JavaScript 程序,初衷是為了減少 DOM 等共享資源的沖突炮姨「越В可是單線程永遠(yuǎn)會面臨著一個問題,那就是某一段代碼阻塞會導(dǎo)致后續(xù)所有的任務(wù)都延遲拍顷。又由于 JavaScript 經(jīng)常需要操作頁面 DOM 和發(fā)送 HTTP 請求哪替,這些 I/O 操作耗時一般都比較長,一旦阻塞菇怀,就會給用戶非常差的使用體驗(yàn)凭舶。
于是便有了事件循環(huán)(event loop)的產(chǎn)生,JavaScript 將一些異步操作或 有I/O 阻塞的操作全都放到一個事件隊列爱沟,先順序執(zhí)行同步 CPU代碼帅霜,等到 JavaScript 引擎沒有同步代碼,CPU 空閑下來再讀取事件隊列的異步事件來依次執(zhí)行呼伸。
這些事件包括:
1 setTimeout() 設(shè)置的異步延遲事件身冀;
2 DOM 操作相關(guān)如布局和繪制事件钝尸;
3 網(wǎng)絡(luò) I/O 如 AJAX 請求事件;
4 用戶操作事件搂根,如鼠標(biāo)點(diǎn)擊珍促、鍵盤敲擊。
由于頁面渲染是 DOM 操作剩愧,會被 JavaScript 引擎放入事件隊列猪叙;
1 alert() 是 window 的內(nèi)置函數(shù),被認(rèn)為是同步 CPU代碼仁卷;
2 JavaScript 引擎會優(yōu)先執(zhí)行同步代碼穴翩,alert 彈窗先出現(xiàn);
3 alert 有特殊的阻塞性質(zhì)锦积,JavaScript 引擎的執(zhí)行被阻塞酌⑴痢;
4 點(diǎn)擊 alert 的“確定”丰介,JavaScript 沒有了阻塞背蟆,執(zhí)行完同步代碼后,又讀取事件隊列里的 DOM 操作哮幢,頁面渲染完成淆储。
由上述原因,導(dǎo)致了詭異的 “Alert執(zhí)行順序問題”家浇。 我們無法將頁面渲染變成同步操作,那么只好把 alert() 變?yōu)楫惒酱a碴裙,從而才能在頁面渲染之后執(zhí)行钢悲。