如果你符合JavaScript高級開發(fā)人員的資格,在編碼面試中很有可能會被問到一些刁鉆的問題。
我知道這不公平。一些不知名的人把你放在角落上下打量,似乎想看你是什么做成的。這是一次不愉快的經(jīng)歷。

你能做什么?
遵循這個建議:“熟能生巧”。通過投入足夠的時間,更好地定期深入了解JavaScript,將改善你的編碼,并順便提高你的面試技巧。
在這篇文章中,你會發(fā)現(xiàn)7個乍一看很簡單,但實際上很棘手的JavaScript面試題。
雖然一開始這些問題看起來是隨機的,但是它們試圖與JavaScript的重要概念掛鉤。所以你最好在下次面試前練習一下!
1. 意外的全局變量
問題
在以下代碼中,typeof a和typeof b的值分別是什么:
function foo() {
let a = b = 0;
a++;
return a;
}
foo();
typeof a; // => ???typeof b; // => ???
答案
讓我們仔細看看第2行:let a = b = 0。這個語句確實聲明了一個局部變量a。但是,它確實聲明了一個全局變量b。
在foo()作用域或全局作用域中都沒有聲明變量 b ”。因此JavaScript將表達式 b = 0 解釋為 window.b = 0。

b是一個偶然創(chuàng)建的全局變量。
在瀏覽器中,上述代碼片段相當于:
function foo() {
let a; window.b = 0; a = window.b; a++;
return a;
}
foo();
typeof a; // => 'undefined'
typeof window.b; // => 'number'
typeof a是 'undefined'。變量a僅在 foo()范圍內(nèi)聲明,在外部范圍內(nèi)不可用。
typeof b等于'number'。b是一個值為 0的全局變量。
2. 數(shù)組 length 屬性
問題
clothes[0] 的值是什么:
const clothes = ['jacket', 't-shirt'];
clothes.length = 0;
clothes[0]; // => ???
答案
數(shù)組對象的 length 屬性有一個 特殊的行為:
減少
length屬性的值有一個副作用,就是會刪除索引位于新舊長度值之間的元素。
因為 length的這種行為,當JavaScript執(zhí)行clothes.length = 0 時,數(shù)組 clothes 中的所有項都被刪除了。
clothes[0] 是undefined,因為 clothes 數(shù)組被清空了。
3. 鷹眼測試
問題
numbers 數(shù)組的內(nèi)容是什么:
const length = 4;
const numbers = [];
for (var i = 0; i < length; i++);{
numbers.push(i + 1);
}
numbers; // => ???
答案
讓我們仔細看看出現(xiàn)在左花括號{前面的分號; :

很容易忽略這個分號,而它創(chuàng)建了一個空語句??照Z句是不做任何事情的語句。
for() 在空語句(什么也不做)上循環(huán)了 4 次,忽略了實際上往數(shù)組里添加元素的代碼塊{ numbers.push(i + 1); }。
上述代碼等同于:
const length = 4;
const numbers = [];
var i;
for (i = 0; i < length; i++) {
// does nothing
}
{
// a simple block
numbers.push(i + 1);
}
numbers; // => [5]
for()遞增變量i直到4。然后JavaScript 進入代碼塊 { numbers.push(i + 1); },將4 + 1 添加 到numbers數(shù)組中。
這樣 numbers 就是 [5].
這個問題背后我的故事
很久以前,當我面試我的第一份工作時,我被問到這個問題。
面試時,我被要求在1小時內(nèi)回答20個編碼問題??照Z句問題位列其中。
當我在匆忙中解決這個問題時,我沒有看到逗號;就在花括號{的前面。所以我答錯成 [1,2,3,4]
我對這些不公平的伎倆有點失望。我問面試官這樣做的原因是什么?面試官回答:
“因為我們需要注重細節(jié)的人。”
幸運的是,我最終沒有在那家公司上班。
你怎么看這個問題?
4. 自動插入分號
問題
arrayFromValue() 返回什么值?
function arrayFromValue(item) {
return
[items];
}
arrayFromValue(10); // => ???
答案
很容易忽略return關(guān)鍵字和[items]表達式之間的換行。
換行使JavaScript自動在return和[items]表達式之間插入一個分號。
這里有一段等價的代碼,它在return后插入分號:
function arrayFromValue(item) {
return; [items];
}
arrayFromValue(10); // => undefined
函數(shù)中的 return; 導致它返回 undefined。
因此 arrayFromValue(10) 的值是 undefined。
查看 這篇文章 閱讀更多關(guān)于自動插入分號的內(nèi)容。
5. 經(jīng)典問題:坑爹的閉包
問題
以下腳本將會在控制臺輸出什么:
let i;
for (i = 0; i < 3; i++) {
const log = () => {
console.log(i); }
setTimeout(log, 100);
}
答案
如果你之前沒有聽說過這個棘手的問題,你的答案很可能是0, 1 和 2,這是不正確的。當我第一次嘗試解答它時,我的答案也是這樣!
執(zhí)行這個代碼段包含兩個步驟。
步驟 1
-
for()迭代3次。在每次迭代過程中,都會創(chuàng)建一個新的函數(shù)log(),它捕獲變量i。然后setTimout()執(zhí)行log()。 - 當
for()循環(huán)完成時,i變量的值為3。
log()是一個捕獲變量 i 的閉包,它在for()循環(huán)的外部作用域定義。重要的是要理解閉包從詞法上捕獲了變量i 。
步驟 2
第2步在 100 毫秒后發(fā)生:
setTimeout()調(diào)用了隊列中的3個log() 回調(diào)。log() 讀取變量 i的當前值,即3,并記錄到控制臺3。
這就是為什么控制臺輸出3, 3 和3。
你知道怎樣讓代碼輸出 0, 1, 和 2嗎?請在評論里寫出你的方案。
6. 浮點數(shù)問題
問題
等號判斷的結(jié)果是什么?
0.1 + 0.2 === 0.3 // => ???
答案
首先,我們看看0.1 + 0.2 的值:
0.1 + 0.2; // => 0.30000000000000004
0.1 和 0.2 的和 不完全等于 0.3,而是略大于 0.3。
由于浮點數(shù)在二進制中的編碼機制,像浮點數(shù)的加法這樣的操作會受到舍入誤差的影響。
簡單地說,直接比較浮點數(shù)是不精確的。
因此 0.1 + 0.2 === 0.3 是 false.
查看 0.30000000000000004.com 獲取更多信息。
7. 變量提升
問題
如果在聲明之前訪問myVar和myConst會發(fā)生什么?
myVar; // => ???myConst; // => ???
var myVar = 'value';
const myConst = 3.14;
答案
變量提升和暫時性死區(qū)是影響JavaScript變量生命周期的兩個重要概念。

在聲明之前訪問 myVar 結(jié)果為undefined。一個被提升的var變量,在它的初始化之前,有一個 undefined的值。
但是,在聲明之前訪問myConst會拋出 ReferenceError。在聲明行const myConst = 3.14之前,const 變量處于暫時死區(qū)。
查看指南 JavaScript 變量提升詳解 ,徹底掌握變量提升的概念。
8. 思考
你可以認為有些問題對面試毫無用處。我也有同樣的感覺,尤其是關(guān)于鷹眼測試。盡管如此,還是有人會問這些問題。
不管怎樣,這些問題中的大多數(shù)都可以測試你是否熟悉JavaScript。如果你在閱讀這篇文章的時候很難答出其中一些問題,這就是提示你接下來要學習什么了!
在面試中問一些刁鉆的問題公平嗎?說說你的看法。
原文
外鏈:http://kaysonli.com/2019/10/23/seven-tricky-js-questions/
交流
歡迎關(guān)注微信公眾號“1024譯站”,獲取國際最新互聯(lián)網(wǎng)技術(shù)資訊。
