一道前端面試題?求大神解答
for (var i = 0; i < 5; i++) {
console.log(i);
}
“小偉,你說說這幾行代碼會輸出什麽?”
當面試官在 Sublime 打出這幾行代碼時,我竟有點蒙蔽。蛤?這不是最簡單的一個循環嗎?是不是有陷阱啊,我思索一下,這好像和我看的那個閉包的題很像啊,這面試官是不是沒寫完啊?有毒啊。
“應該是直接輸出 0 到 4 吧...”,我弱弱的說到。
“是啊,別緊張,這題沒啥陷阱,我就是隨便寫一下。”
(Excuse me?面試官你是來搞笑的嗎,嚇死老子了!)
“那你在看看這幾行代碼會輸出什麽?”
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i);
}, 1000 * i);
}
額,什麽鬼,怎麽還不是我背了那麽多遍的那道閉包題,讓我想想。 setTimeout 會延遲執行,那麽執行到 console.log 的時候,其實 i 已經變成 5 了,對,就是這樣,這麽簡單怎麽可能難到老子。
“應該是開始輸出一個 5,然後每隔一秒再輸出一個 5,一共 5 個 5。”
“對,那應該怎麽改才能輸出 0 到 4 呢?”
終於到我熟悉的了,加個閉包就解決了,穩!
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!媽媽再也不用擔心我的面試了。
轉載與‘最騷的就是你’
一道前端面試題?求大神解答