日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

80%應聘者都不及格的JS面試題

瀏覽:213日期:2024-05-27 08:12:46

80%應聘者都不及格的JS面試題

寫在前面,筆者在做面試官這 2 年多的時間內,面試了數百個前端工程師,驚訝的發現,超過 80% 的候選人對下面這道題的回答情況連及格都達不到。這究竟是怎樣神奇的一道面試題?他考察了候選人的哪些能力?對正在讀本文的你有什么啟示?且聽我慢慢道來

不起眼的開始

招聘前端工程師,尤其是中高級前端工程師,扎實的 JS 基礎絕對是必要條件,基礎不扎實的工程師在面對前端開發中的各種問題時大概率會束手無策。在考察候選人 JS 基礎的時候,我經常會提供下面這段代碼,然后讓候選人分析它實際運行的結果:

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

這段代碼很短,只有 7 行,我想,能讀到這里的同學應該不需要我逐行解釋這段代碼在做什么吧。候選人面對這段代碼時給出的結果也不盡相同,以下是典型的答案:

A. 20% 的人會快速掃描代碼,然后給出結果:0,1,2,3,4,5; B. 30% 的人會拿著代碼逐行看,然后給出結果:5,0,1,2,3,4; C. 50% 的人會拿著代碼仔細琢磨,然后給出結果:5,5,5,5,5,5;

只要你對 JS 中同步和異步代碼的區別、變量作用域、閉包等概念有正確的理解,就知道正確答案是 C,代碼的實際輸出是:

2017-03-18T00:43:45.873Z 5 2017-03-18T00:43:46.866Z 5 2017-03-18T00:43:46.868Z 5 2017-03-18T00:43:46.868Z 5 2017-03-18T00:43:46.868Z 5 2017-03-18T00:43:46.868Z 5

接下來我會追問:如果我們約定,用箭頭表示其前后的兩次輸出之間有 1 秒的時間間隔,而逗號表示其前后的兩次輸出之間的時間間隔可以忽略,代碼實際運行的結果該如何描述?會有下面兩種答案:

A. 60% 的人會描述為:5 -> 5 -> 5 -> 5 -> 5,即每個 5 之間都有 1 秒的時間間隔; B. 40% 的人會描述為:5 -> 5,5,5,5,5,即第 1 個 5 直接輸出,1 秒之后,輸出 5 個 5;

這就要求候選人對 JS 中的定時器工作機制非常熟悉,循環執行過程中,幾乎同時設置了 5 個定時器,一般情況下,這些定時器都會在 1 秒之后觸發,而循環完的輸出是立即執行的,顯而易見,正確的描述是 B。

如果到這里算是及格的話,100 個人參加面試只有 20 人能及格,讀到這里的同學可以仔細思考,你及格了么?

追問 1:閉包

如果這道題僅僅是考察候選人對 JS 異步代碼、變量作用域的理解,局限性未免太大,接下來我會追問,如果期望代碼的輸出變成:5 -> 0,1,2,3,4,該怎么改造代碼?熟悉閉包的同學很快能給出下面的解決辦法:

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

巧妙的利用 IIFE(Immediately Invoked Function Expression:聲明即執行的函數表達式)來解決閉包造成的問題,確實是不錯的思路,但是初學者可能并不覺得這樣的代碼很好懂,至少筆者初入門的時候這里琢磨了一會兒才真正理解。

有沒有更符合直覺的做法?答案是有,我們只需要對循環體稍做手腳,讓負責輸出的那段代碼能拿到每次循環的 i 值即可。該怎么做呢?利用 JS 中基本類型(Primitive Type)的參數傳遞是按值傳遞(Pass by Value)的特征,不難改造出下面的代碼:

var output = function (i) { setTimeout(function() { console.log(new Date, i); }, 1000); }; for (var i = 0; i < 5; i++) { output(i); // 這里傳過去的 i 值被復制了 } console.log(new Date, i);

能給出上述 2 種解決方案的候選人可以認為對 JS 基礎的理解和運用是不錯的,可以各加 10 分。當然實際面試中還有候選人給出如下的代碼:

for (let i = 0; i < 5; i++) { setTimeout(function() { console.log(new Date, i); }, 1000); } console.log(new Date, i);

細心的同學會發現,這里只有個非常細微的變動,即使用 ES6 塊級作用域(Block Scope)中的 let 替代了 var,但是代碼在實際運行時會報錯,因為最后那個輸出使用的 i 在其所在的作用域中并不存在,i 只存在于循環內部。

能想到 ES6 特性的同學雖然沒有答對,但是展示了自己對 ES6 的了解,可以加 5 分,繼續進行下面的追問。

追問 2:ES6

有經驗的前端同學讀到這里可能有些不耐煩了,扯了這么多,都是他知道的內容,先別著急,挑戰的難度會繼續增加。

接著上文繼續追問:如果期望代碼的輸出變成 0 -> 1 -> 2 -> 3 -> 4 -> 5,并且要求原有的代碼塊中的循環和兩處 console.log 不變,該怎么改造代碼?新的需求可以精確的描述為:代碼執行時,立即輸出 0,之后每隔 1 秒依次輸出 1,2,3,4,循環結束后在大概第 5 秒的時候輸出 5(這里使用大概,是為了避免鉆牛角尖的同學陷進去,因為 JS 中的定時器觸發時機有可能是不確定的,具體可參見 How Javascript Timers Work)。

看到這里,部分同學會給出下面的可行解:

for (var i = 0; i < 5; i++) { (function(j) { setTimeout(function() { console.log(new Date, j); }, 1000 * j)); // 這里修改 0~4 的定時器時間 })(i); } setTimeout(function() { // 這里增加定時器,超時設置為 5 秒 console.log(new Date, i); }, 1000 * i);

不得不承認,這種做法雖粗暴有效,但是不算是能額外加分的方案。如果把這次的需求抽象為:在系列異步操作完成(每次循環都產生了 1 個異步操作)之后,再做其他的事情,代碼該怎么組織?聰明的你是不是想起了什么?對,就是 Promise。

可能有的同學會問,不就是在控制臺輸出幾個數字么?至于這樣殺雞用牛刀?你要知道,面試官真正想考察的是候選人是否具備某種能力和素質,因為在現代的前端開發中,處理異步的代碼隨處可見,熟悉和掌握異步操作的流程控制是成為合格開發者的基本功。

順著下來,不難給出基于 Promise 的解決方案(既然 Promise 是 ES6 中的新特性,我們的新代碼使用 ES6 編寫是不是會更好?如果你這么寫了,大概率會讓面試官心生好感):

const tasks = []; for (var i = 0; i < 5; i++) { // 這里 i 的聲明不能改成 let,如果要改該怎么做? ((j) => { tasks.push(new Promise((resolve) => { setTimeout(() => { console.log(new Date, j); resolve(); // 這里一定要 resolve,否則代碼不會按預期 work }, 1000 * j); // 定時器的超時時間逐步增加 })); })(i); } Promise.all(tasks).then(() => { setTimeout(() => { console.log(new Date, i); }, 1000); // 注意這里只需要把超時設置為 1 秒 });

相比而言,筆者更傾向于下面這樣看起來更簡潔的代碼,要知道編程風格也是很多面試官重點考察的點,代碼閱讀時的顆粒度更小,模塊化更好,無疑會是加分點。

const tasks = []; // 這里存放異步操作的 Promise const output = (i) => new Promise((resolve) => { setTimeout(() => { console.log(new Date, i); resolve(); }, 1000 * i); }); // 生成全部的異步操作 for (var i = 0; i < 5; i++) { tasks.push(output(i)); } // 異步操作完成之后,輸出最后的 i Promise.all(tasks).then(() => { setTimeout(() => { console.log(new Date, i); }, 1000); });

讀到這里的同學,恭喜你,你下次面試遇到類似的問題,至少能拿到 80 分。

我們都知道使用 Promise 處理異步代碼比回調機制讓代碼可讀性更高,但是使用 Promise 的問題也很明顯,即如果沒有處理 Promise 的 reject,會導致錯誤被丟進黑洞,好在新版的 Chrome 和 Node 7.x 能對未處理的異常給出 Unhandled Rejection Warning,而排查這些錯誤還需要一些特別的技巧(瀏覽器、Node.js)。

追問 3:ES7

既然你都看到這里了,那就再堅持 2 分鐘,接下來的內容會讓你明白你的堅持是值得的。

多數面試官在決定聘用某個候選人之前還需要考察另外一項重要能力,即技術自驅力,直白的說就是候選人像有內部的馬達在驅動他,用漂亮的方式解決工程領域的問題,不斷的跟隨業務和技術變得越來越牛逼,究竟什么是牛逼?建議閱讀程序人生的這篇剖析。

回到正題,既然 Promise 已經被拿下,如何使用 ES7 中的 async await 特性來讓這段代碼變的更簡潔?你是否能夠根據自己目前掌握的知識給出答案?請在這里暫停 1 分鐘,思考下。

下面是筆者給出的參考代碼:

// 模擬其他語言中的 sleep,實際上可以是任何異步操作 const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); }); (async () => { // 聲明即執行的 async 函數表達式 for (var i = 0; i < 5; i++) { await sleep(1000); console.log(new Date, i); } await sleep(1000); console.log(new Date, i); })();

總結

感謝你花時間讀到這里,相信你收獲的不僅僅是用 JS 精確控制代碼輸出的各種技巧,更是對于前端工程師的成長期許:扎實的語言基礎、與時俱進的能力、強大技術自驅力。

來自:http://developer.51cto.com/art/201704/536696.htm

標簽: JavaScript
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品二区影院| 国产一区二区三区亚洲| 精品久久一区| 国产欧美大片| 在线亚洲一区| 激情五月色综合国产精品| 日韩一区二区中文| 日韩一区二区在线免费| av日韩中文| 色偷偷色偷偷色偷偷在线视频| 成人午夜网址| 在线天堂资源www在线污| 日本蜜桃在线观看视频| 亚洲日本网址| 激情自拍一区| 国产视频一区在线观看一区免费| 欧美一级精品| 欧美jjzz| 中日韩男男gay无套| 欧美大黑bbbbbbbbb在线| 亚洲一级高清| 天堂成人国产精品一区| 亚洲精品伊人| 日韩va亚洲va欧美va久久| 日韩高清一区| 国产精品毛片aⅴ一区二区三区| 国产日韩欧美在线播放不卡| 国产精区一区二区| 精品精品久久| 日韩一区二区中文| 香蕉精品视频在线观看| 国产亚洲毛片| 日韩高清三区| 国内揄拍国内精品久久| 日产精品一区二区| 欧美日韩精品一区二区视频| 9久re热视频在线精品| 视频一区二区三区在线| 欧美亚洲三级| yellow在线观看网址| 久久黄色影院| 蜜桃一区二区三区在线观看| 911精品国产| av资源亚洲| 国产精品美女久久久| 日韩 欧美一区二区三区| 久久精品国产免费| 欧美影院三区| 日本成人在线不卡视频| 久久在线91| 日韩免费久久| 视频在线在亚洲| 久久99久久久精品欧美| 国产精品av一区二区| 亚洲免费毛片| 老色鬼精品视频在线观看播放| 日韩精品一区二区三区免费观看| 亚洲制服少妇| 国产精品mm| 久久高清免费| 日韩欧美另类中文字幕| 老司机精品视频网| 亚洲深夜影院| 精品日韩一区| 宅男在线一区| 国产精品.xx视频.xxtv| 蜜桃视频欧美| 国产剧情在线观看一区| 欧美91精品| 国产精品视频一区视频二区| 久久一区二区三区喷水| 欧美久久久网站| 国产精品99免费看| 国产日韩欧美在线播放不卡| 国产91精品对白在线播放| 91嫩草精品| 黄色欧美日韩| 国产a亚洲精品| 日韩一区二区三区精品视频第3页 日韩一区二区三区免费视频 | 国产成人精品一区二区免费看京| 欧美日韩国产高清| 国产aⅴ精品一区二区三区久久| 99热免费精品| 国产乱码午夜在线视频| 日韩国产在线观看一区| 女同性一区二区三区人了人一 | 国产欧美精品| 免费精品国产的网站免费观看| 国产精品久久久久久模特 | yellow在线观看网址| 日韩精品一区二区三区免费视频| 亲子伦视频一区二区三区| 欧美日韩精品一区二区三区视频| 午夜国产一区二区| 色偷偷色偷偷色偷偷在线视频| 欧美一区久久| 视频一区视频二区中文| 999久久久免费精品国产| 欧美国产专区| 日韩精品一级二级| 99精品综合| 精品三级在线观看视频| 欧美亚洲三区| 美国三级日本三级久久99 | av不卡在线看| 日韩精品欧美| 精品国产亚洲一区二区三区在线 | 麻豆网站免费在线观看| 国产美女亚洲精品7777| 一区二区三区四区日韩| 亚洲精品一区二区在线看| 福利在线一区| 国产免费av国片精品草莓男男| 亚洲区第一页| 日韩一区二区免费看| 久久激情一区| 午夜欧美巨大性欧美巨大| 91欧美在线| 69堂免费精品视频在线播放| 亚洲一区二区网站| 亚洲性图久久| 97精品一区| 日韩不卡一区| a国产在线视频| 福利一区二区免费视频| 精品三级国产| 精品理论电影在线| 精品一区二区三区免费看| 欧美成人一二区| 国产精品久久国产愉拍| 欧美日韩亚洲一区| 日韩不卡免费视频| 日韩激情综合| 97成人在线| 国产欧美日韩精品一区二区免费 | 国产日韩1区| 久久国产日韩欧美精品| 欧美在线看片| 国产乱码精品一区二区三区亚洲人| 欧美在线不卡| 国产精品magnet| 牛牛精品成人免费视频| 精品深夜福利视频| 成人影视亚洲图片在线| 91亚洲国产高清| 精品亚洲成人| 日韩激情一区| 亚洲国产成人精品女人| 亚洲欧美日韩国产综合精品二区| 在线国产精品一区| 日日夜夜免费精品视频| 日本天堂一区| 精品一区二区三区免费看| 色黄视频在线观看| 91精品91| 日本亚洲欧美天堂免费| 国产麻豆一区二区三区| 国产精品久久久久久久免费观看 | 福利在线免费视频| 久久美女精品| 亚洲精一区二区三区| 老司机精品视频网| 91九色精品| 国产欧美亚洲精品a| 色在线视频观看| 国产精品女主播一区二区三区| 亚洲精品第一| 国产精品亚洲四区在线观看| 精品无人区麻豆乱码久久久| 亚洲www啪成人一区二区| 高清av不卡| 久久国产亚洲精品| 国产亚洲精品久久久久婷婷瑜伽| 在线午夜精品| 婷婷综合社区| 青青伊人久久| 久久免费视频66| www成人在线视频| 欧美日韩免费观看一区=区三区| 妖精视频成人观看www| 在线看片一区| 欧美亚洲综合视频| 精品丝袜久久| 亚洲韩日在线| 日日夜夜免费精品| 黑人精品一区| 香蕉久久精品| 综合国产在线| 亚洲在线电影| 高潮久久久久久久久久久久久久| 啪啪国产精品| 免费在线观看一区二区三区| 日本午夜精品久久久| 香蕉视频亚洲一级| 丝袜国产日韩另类美女| 国产毛片久久久| 日韩国产一区二区| 日韩中文字幕视频网| 欧美黄色一区| 亚洲精品国产偷自在线观看|