自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

這一次,徹底解決面試中【看代碼說(shuō)結(jié)果】的問(wèn)題!

開(kāi)發(fā) 前端
由于 JavaScript 是單線程的,它就像一家只有一個(gè)窗口的銀行,客戶(hù)需要一一排隊(duì)來(lái)處理交易。同樣,JavaScript 任務(wù)也需要按順序執(zhí)行,一個(gè)接一個(gè)。如果一項(xiàng)任務(wù)花費(fèi)太長(zhǎng)時(shí)間,則下一項(xiàng)任務(wù)必須等待。

Hello,大家好,我是 Sunday。

【看代碼說(shuō)結(jié)果】一直是前端面試中的常見(jiàn)問(wèn)題。最近在陪幾個(gè)同學(xué)面試過(guò)程中,幾乎每個(gè)中、大廠的面試都會(huì)遇到一個(gè)或幾個(gè)這樣的問(wèn)題。

圖片圖片

陪同學(xué)面試中遇到的真題

雖然這樣的問(wèn)題如此高頻,但是能夠回答好的同學(xué)卻寥寥無(wú)幾。

每次事后跟同學(xué)溝通,得到的結(jié)果都是:“實(shí)際開(kāi)發(fā)中沒(méi)有這么寫(xiě)的,NND 奇葩面試題!” 大家是不是也會(huì)有相同的感受呢?

是的!實(shí)際開(kāi)發(fā)中我們肯定不會(huì)寫(xiě)出面試題里的凌亂場(chǎng)景。但是,我們不要忘記,學(xué)習(xí)的目的是:為了拿到更高薪資的 offer!,所以對(duì)很多同學(xué)而言 面試 比 實(shí)際開(kāi)發(fā) 更重要! 只有很好的解決了 面試 的問(wèn)題,大家才可以拿到滿(mǎn)意的 offer。

所以,解決【看代碼說(shuō)結(jié)果】的問(wèn)題就變得至關(guān)重要了。那么咱們今天,就好好地來(lái)聊聊 JS 中的執(zhí)行機(jī)制問(wèn)題,幫大家徹底理解 JS 的執(zhí)行邏輯!

關(guān)于 JavaScript 線程基礎(chǔ)邏輯

JavaScript 是一種單線程語(yǔ)言。

雖然最新的 HTML5 中引入了 Web Worker,但 JavaScript 單線程的核心保持不變。

因此,JavaScript中所有的“多線程”都是用單線程模擬的,JavaScript中的所有多線程都是騙人的!

JavaScript 事件循環(huán)

由于 JavaScript 是單線程的,它就像一家只有一個(gè)窗口的銀行,客戶(hù)需要一一排隊(duì)來(lái)處理交易。

同樣,JavaScript 任務(wù)也需要按順序執(zhí)行,一個(gè)接一個(gè)。如果一項(xiàng)任務(wù)花費(fèi)太長(zhǎng)時(shí)間,則下一項(xiàng)任務(wù)必須等待。

那么問(wèn)題就來(lái)了:如果我們想瀏覽新聞,但新聞中的高清圖片加載緩慢,我們的網(wǎng)頁(yè)是否要一直卡住,直到圖片完全顯示出來(lái)?

因此,JS將任務(wù)分為兩類(lèi):

  • 同步任務(wù)
  • 異步任務(wù)

當(dāng)我們打開(kāi)一個(gè)網(wǎng)站時(shí),網(wǎng)頁(yè)的渲染過(guò)程由一堆同步任務(wù)組成,例如:骨架屏幕、頁(yè)面元素

消耗大量資源且需要很長(zhǎng)時(shí)間才能完成的任務(wù)(例如:加載圖像、音樂(lè)文件)則是異步的

圖片圖片

  • 同步和異步任務(wù)進(jìn)入不同的執(zhí)行“地方”,同步任務(wù)進(jìn)入主線程,異步任務(wù)進(jìn)入事件表并注冊(cè)函數(shù)。
  • 當(dāng)指定的任務(wù)完成時(shí),事件表會(huì)將這個(gè)函數(shù)移動(dòng)到事件隊(duì)列中。
  • 主線程內(nèi)的任務(wù)完成后,會(huì)從Event Queue中讀取相應(yīng)的函數(shù)并在主線程中執(zhí)行。
  • 上述過(guò)程會(huì)不斷重復(fù),通常稱(chēng)為事件循環(huán)。

那么 JS 是如何知道主線程為空的呢?

在 JavaScript 引擎有一個(gè)監(jiān)控進(jìn)程,不斷檢查主線程執(zhí)行棧是否為空。一旦為空,它就會(huì)去事件隊(duì)列檢查是否有任何函數(shù)正在等待調(diào)用。

如下面的代碼所示:

let data = [];
$.ajax({
    url:www.lgdsunday.club,
    data:data,
    success:() => {
        console.log('發(fā)送成功!');
    }
})
console.log('代碼執(zhí)行完成');

上面是一個(gè)簡(jiǎn)單的ajax請(qǐng)求代碼:

  • ajax進(jìn)入事件表并注冊(cè)回調(diào)函數(shù)success。
  • 執(zhí)行console. log(‘發(fā)送成功!’)。
  • ajax事件完成,回調(diào)函數(shù)成功進(jìn)入事件隊(duì)列。
  • 主線程success從事件隊(duì)列中讀取并執(zhí)行回調(diào)函數(shù)。

通過(guò)上面的文字和代碼,大家應(yīng)該對(duì)JavaScript中的執(zhí)行順序有了初步的了解了吧。

那么接下來(lái)咱們來(lái)看一個(gè) 擾亂執(zhí)行順序的 “元兇” setTimeout

萬(wàn)惡的 setTimeout

setTimeout 可以延遲執(zhí)行代碼,比如:

setTimeout(() => {
    task();
},3000)
console.log('一個(gè)普通的打印');

根據(jù)我們之前的結(jié)論,setTimeout是異步的。所以,同步任務(wù)console.log應(yīng)該先執(zhí)行。因此,我們的結(jié)論是:

// 一個(gè)普通的打印
// task()

但是,這里我們要注意 3000 毫秒并不是 task 的執(zhí)行時(shí)間,而是 task 進(jìn)入任務(wù)隊(duì)列(主線程)的時(shí)間

  • 3秒后,計(jì)時(shí)事件timeout完成。
  • task()進(jìn)入任務(wù)隊(duì)列(主線程)

即面試中常提到的 setTimeout 定時(shí)并不準(zhǔn)確的問(wèn)題 字節(jié)面試:如何實(shí)現(xiàn)準(zhǔn)時(shí)的setTimeout 可以看下之前的這篇文章

那么同樣的道理,在面試中常見(jiàn)的 setTimeout(fn, 0) 的延遲 0 毫秒 是什么意思呢?

setTimeout(fn ,0)是指定當(dāng)堆棧中的所有同步任務(wù)完成且堆棧變空時(shí),應(yīng)在主線程上最早可用的空閑時(shí)間執(zhí)行某個(gè)任務(wù),而不需要等待任何額外的秒數(shù)。

所以,setTimeout(fn, 0) 并不會(huì)立刻執(zhí)行

宏任務(wù)與微任務(wù)

宏任務(wù)與微任務(wù)的概念在這種題目中也是必須要掌握的。

  • 宏任務(wù):包括整體腳本代碼、setTimeout、setInterval
  • 微任務(wù):Promise、process.nextTick

事件循環(huán)中事件的順序決定了JavaScript代碼的執(zhí)行順序。

  • 輸入整個(gè)腳本(宏任務(wù))后,它開(kāi)始第一個(gè)循環(huán)
  • 然后它執(zhí)行所有微任務(wù)。接下來(lái),又從宏任務(wù)開(kāi)始,直到一個(gè)任務(wù)隊(duì)列完成后,才再次執(zhí)行所有的微任務(wù)

我們通過(guò)一段代碼來(lái)看下這個(gè)問(wèn)題:

setTimeout(function() {
    console.log('setTimeout');
})

new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})

console.log('console');
  • 這段代碼作為宏任務(wù),進(jìn)入主線程。
  • 當(dāng)遇到 setTimeout 時(shí),其回調(diào)函數(shù)被注冊(cè)并調(diào)度到宏任務(wù)事件隊(duì)列中。(注冊(cè)流程同上,下文不再贅述)
  • 接下來(lái),當(dāng)遇到 Promise 時(shí),new Promise立即執(zhí)行,并將該then函數(shù)分派到微任務(wù)事件隊(duì)列中。
  • 當(dāng)遇到 console.log() 時(shí),立即執(zhí)行。
  • 在將整個(gè)腳本作為第一個(gè)宏任務(wù)執(zhí)行之后。我們發(fā)現(xiàn)它 then 位于微任務(wù)事件隊(duì)列中并被執(zhí)行。
  • 第一輪事件循環(huán)結(jié)束
  • 第二輪循環(huán)開(kāi)始;當(dāng)然是從宏任務(wù)Event Queue開(kāi)始。隊(duì)列中對(duì)應(yīng)setTimeout的回調(diào)函數(shù)立即被執(zhí)行
  • 結(jié)尾
責(zé)任編輯:武曉燕 來(lái)源: 程序員Sunday
相關(guān)推薦

2025-04-09 10:36:32

2024-05-20 00:00:00

代碼主線程

2024-05-15 10:14:00

CRDT數(shù)據(jù)類(lèi)型協(xié)同編輯

2019-11-08 16:05:54

Promise前端鏈?zhǔn)秸{(diào)用

2024-03-11 08:47:30

CRDT數(shù)據(jù)類(lèi)型協(xié)同編輯

2019-09-12 09:40:34

秒殺系統(tǒng)高并發(fā)

2021-07-03 08:59:49

動(dòng)態(tài)代理JDK

2018-08-07 14:45:52

編程語(yǔ)言JavaScripthtml

2020-09-28 14:41:24

Event Loop

2021-08-29 08:14:30

GPU CSS gpu

2019-06-05 13:00:00

2016-03-31 17:01:26

桂林甲天下

2018-07-23 16:13:27

Google歐盟Android

2020-08-13 07:04:45

跨域CORS瀏覽器

2019-04-12 11:25:24

華為

2021-03-11 12:15:37

Kubernetes云原生容器

2016-11-08 07:58:02

樂(lè)視難關(guān)科技新聞早報(bào)

2014-07-18 17:14:16

小米蘋(píng)果雷軍

2016-01-06 11:15:03

VR

2021-04-28 09:55:52

JavaLock接口并發(fā)編程
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)