一次圍繞setTimeout的前端面試經(jīng)驗(yàn)分享
前言
前端這個(gè)近年的熱門領(lǐng)域,搞事氣氛特別強(qiáng)烈,我朋友小偉最近就在瘋狂面試,遇到了許多有趣的面試官,有趣的面試題,我來(lái)幫這個(gè)搞事 boy 轉(zhuǎn)述一下。
具體如下:
以下是我一個(gè)朋友的故事,真的不是我。
for (var i = 0; i < 5; i++) { console.log(i); }
“小偉,你說(shuō)說(shuō)這幾行代碼會(huì)輸出什么?”
當(dāng)面試官在 Sublime 打出這幾行代碼時(shí),我竟有點(diǎn)蒙蔽。蛤?這不是最簡(jiǎn)單的一個(gè)循環(huán)嗎?是不是有陷阱啊,我思索一下,這好像和我看的那個(gè)閉包的題很像啊,這面試官是不是沒(méi)寫(xiě)完啊?有毒啊。
“應(yīng)該是直接輸出 0 到 4 吧...”,我弱弱的說(shuō)到。
“是啊,別緊張,這題沒(méi)啥陷阱,我就是隨便寫(xiě)一下?!?/p>
(Excuse me?面試官你是來(lái)搞笑的嗎,嚇?biāo)览献恿耍。?/p>
“那你在看看這幾行代碼會(huì)輸出什么?”
for (var i = 0; i < 5; i++) { setTimeout(function() { console.log(i); }, 1000 * i); }
額,什么鬼,怎么還不是我背了那么多遍的那道閉包題,讓我想想。 setTimeout 會(huì)延遲執(zhí)行,那么執(zhí)行到 console.log 的時(shí)候,其實(shí) i 已經(jīng)變成 5 了,對(duì),就是這樣,這么簡(jiǎn)單怎么可能難到老子。
“應(yīng)該是開(kāi)始輸出一個(gè) 5,然后每隔一秒再輸出一個(gè) 5,一共 5 個(gè) 5?!?/p>
“對(duì),那應(yīng)該怎么改才能輸出 0 到 4 呢?”
終于到我熟悉的了,加個(gè)閉包就解決了,穩(wěn)!
for (var i = 0; i < 5; i++) { (function(i) { setTimeout(function() { console.log(i); }, i * 1000); })(i); }
“很好,那你能說(shuō)一下,我刪掉這個(gè) i 會(huì)發(fā)生什么嗎?”
for (var i = 0; i < 5; i++) { (function() { setTimeout(function() { console.log(i); }, i * 1000); })(i); }
“這樣子的話,內(nèi)部其實(shí)沒(méi)有對(duì) i 保持引用,其實(shí)會(huì)變成輸出 5?!?/p>
“很好,那我給你改一下,你看看會(huì)輸出什么?”
for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000); }
蛤?什么鬼,這是什么情況,讓我想想。這里給 setTimeout 傳遞了一個(gè)立即執(zhí)行函數(shù)。額,setTimeout 可以接受函數(shù)或者字符串作為參數(shù),那么這里立即執(zhí)行函數(shù)是個(gè)啥呢,應(yīng)該是個(gè) undefined ,也就是說(shuō)等價(jià)于:
setTimeout(undefined, ...);
而立即執(zhí)行函數(shù)會(huì)立即執(zhí)行,那么應(yīng)該是立馬輸出的。
“應(yīng)該是立馬輸出 0 到 4 吧?!?/p>
“哎喲,不錯(cuò)哦,最后一題,你對(duì) Promise 了解吧?”
“還可以吧...”
“OK,那你試試這道題?!?/p>
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?。。?!我想靜靜!
這道題應(yīng)該考察我 JavaScript 的運(yùn)行機(jī)制的,讓我理一下思路。
首先先碰到一個(gè) setTimeout,于是會(huì)先設(shè)置一個(gè)定時(shí),在定時(shí)結(jié)束后將傳遞這個(gè)函數(shù)放到任務(wù)隊(duì)列里面,因此開(kāi)始肯定不會(huì)輸出 1 。
然后是一個(gè) Promise,里面的函數(shù)是直接執(zhí)行的,因此應(yīng)該直接輸出 2 3 。
然后,Promise 的 then 應(yīng)當(dāng)會(huì)放到當(dāng)前 tick 的最后,但是還是在當(dāng)前 tick 中。
因此,應(yīng)當(dāng)先輸出 5,然后再輸出 4 。
最后在到下一個(gè) tick,就是 1 。
“2 3 5 4 1”
“好滴,等待下一輪面試吧?!?/p>
So easy!媽媽再也不用擔(dān)心我的面試了。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
- js前端面試題及答案整理(一)
- for循環(huán) + setTimeout 結(jié)合一些示例(前端面試題)
- 整理一些最近經(jīng)常遇到的前端面試題
- 前端面試知識(shí)點(diǎn)錦集(JavaScript篇)
- js前端面試之同步與異步問(wèn)題詳解
- 常見(jiàn)前端面試題及答案
- 前端面試題及答案整理(二)
- 「中高級(jí)前端面試」JavaScript手寫(xiě)代碼無(wú)敵秘籍(推薦)
- 收集前端面試題之url、href、src
- 前端面試知識(shí)點(diǎn)目錄一覽
- Vue面試題及Vue知識(shí)點(diǎn)整理
- 關(guān)于vue面試題匯總
- 2019年度web前端面試題總結(jié)(主要為Vue面試題)
相關(guān)文章
基于JS+Canves實(shí)現(xiàn)點(diǎn)擊按鈕水波紋效果
本文給大家分享基于js和canves實(shí)現(xiàn)點(diǎn)擊按鈕水波紋效果,效果非常逼真,對(duì)此感興趣的朋友一起看看吧2016-09-09Fastest way to build an HTML string(拼裝html字符串的最快方法)
Fastest way to build an HTML stringPosted in 'Code Snippets, JavaScript' by James on May 29th, 20092011-08-08基于substring()和substr()的使用以及區(qū)別(實(shí)例講解)
下面小編就為大家分享一篇基于substring()和substr()的使用以及區(qū)別實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12利用javascript實(shí)現(xiàn)的三種圖片放大鏡效果實(shí)例(附源碼)
這篇文章主要介紹了利用javascript實(shí)現(xiàn)的幾種放大鏡效果,很實(shí)用一款漂亮的js圖片放大鏡特效,常見(jiàn)于電商網(wǎng)站上產(chǎn)品頁(yè),用來(lái)放大展示圖片細(xì)節(jié),很有實(shí)用性,推薦下載學(xué)習(xí)研究。文中提供了完整的源碼供大家下載,需要的朋友可以參考借鑒,一起來(lái)看看吧。2017-01-01原生js實(shí)現(xiàn)簡(jiǎn)單貪吃蛇小游戲
這篇文章主要為大家詳細(xì)介紹了原生js實(shí)現(xiàn)貪吃蛇小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06