一道前端面試題?求大神解答

金三銀四搞事季,前端這個近年的熱門領域,搞事氣氛特別強烈,我朋友小偉最近就在瘋狂面試,遇到了許多有趣的面試官,有趣的面試題,我來幫這個搞事 boy 轉述一下。javascript

如下是我一個朋友的故事,真的不是我。
for (var i = 0; i < 5; i++) { console.log(i); } 

「小偉,你說說這幾行代碼會輸出什麼?」前端

當面試官在 Sublime 打出這幾行代碼時,我竟有點矇蔽。蛤?這不是最簡單的一個循環嗎?是否是有陷阱啊,我思索一下,這好像和我看的那個閉包的題很像啊,這面試官是否是沒寫完啊?有毒啊。java

「應該是直接輸出 0 到 4 吧...」,我弱弱的說到。面試

「是啊,別緊張,這題沒啥陷阱,我就是隨便寫一下。」bash

(Excuse me?面試官你是來搞笑的嗎,嚇死老子了!)閉包

「那你在看看這幾行代碼會輸出什麼?」函數

for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000 * i); } 

額,什麼鬼,怎麼還不是我背了那麼多遍的那道閉包題,讓我想一想。 setTimeout 會延遲執行,那麼執行到 console.log 的時候,其實 i 已經變成 5 了,對,就是這樣,這麼簡單怎麼可能難到老子。ui

「應該是開始輸出一個 5,而後每隔一秒再輸出一個 5,一共 5 個 5。」spa

「對,那應該怎麼改才能輸出 0 到 4 呢?」code

終於到我熟悉的了,加個閉包就解決了,穩!

for (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); } 

「很好,那你能說一下,我刪掉這個 i 會發生什麼嗎?」

for (var i = 0; i < 5; i++) { (function() { setTimeout(function() { console.log(i); }, i * 1000); })(i); } 

「這樣子的話,內部其實沒有對 i 保持引用,其實會變成輸出 5。」

「很好,那我給你改一下,你看看會輸出什麼?」

for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000); } 

蛤?什麼鬼,這是什麼狀況,讓我想一想。這裏給 setTimeout 傳遞了一個當即執行函數。額,setTimeout 能夠接受函數或者字符串做爲參數,那麼這裏當即執行函數是個啥呢,應該是個 undefined ,也就是說等價於:

setTimeout(undefined, ...); 

而當即執行函數會當即執行,那麼應該是立馬輸出的。

「應該是立馬輸出 0 到 4 吧。」

「哎喲,不錯哦,最後一題,你對 Promise 瞭解吧?」

「還能夠吧...」

「OK,那你試試這道題。」

setTimeout(function() { console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for( var i=0 ; i<10000 ; i++ ) { i == 9999 && resolve(); } console.log(3); }).then(function() { console.log(4); }); console.log(5); 

WTF!!!!我想靜靜!

這道題應該考察我 JavaScript 的運行機制的,讓我理一下思路。

首先先碰到一個 setTimeout,因而會先設置一個定時,在定時結束後將傳遞這個函數放到任務隊列裏面,所以開始確定不會輸出 1 。

而後是一個 Promise,裏面的函數是直接執行的,所以應該直接輸出 2 3 。

而後,Promise 的 then 應當會放到當前 tick 的最後,可是仍是在當前 tick 中。

所以,應當先輸出 5,而後再輸出 4 。

最後在到下一個 tick,就是 1 。

「2 3 5 4 1」

「好滴,等待下一輪面試吧。」

So easy!媽媽不再用擔憂個人面試了。

相關文章
相關標籤/搜索