你應該知道的25道Javascript面試題
題目來自 25 Essential JavaScript Interview Questions。閑來無事,正好切一下。 一
What is a potential pitfall with using typeof bar === "object" to determine if bar is an object? How can this pitfall be avoided?
老生常談的問題,用 typeof 是否能準確判斷一個物件變數,答案是否定的,null 的結果也是 object,Array 的結果也是 object,有時候我們需要的是 "純粹" 的 object 對象。
如何規避這個問題。
var obj = {};// 1console.log((obj !== null) && (typeof obj === "object") && (toString.call(obj) !== "[object Array]"));// 2console.log(Object.prototype.toString.call(obj) === "[object Object]");
二
What will the code below output to the console and why?
(function(){ var a = b = 3;})();console.log("a defined? " + (typeof a !== 'undefined'));console.log("b defined? " + (typeof b !== 'undefined'));
這題不難,IIFE 中的賦值過程其實是(賦值過程從右至左):
(function(){ b = 3; var a = b;})();
接下去就不難了,a 是局部變數,b 是全域變數。 三
What will the code below output to the console and why?
var myObject = { foo: "bar", func: function() { var self = this; console.log("outer func: this.foo = " + this.foo); console.log("outer func: self.foo = " + self.foo); (function() { console.log("inner func: this.foo = " + this.foo); console.log("inner func: self.foo = " + self.foo); }()); }};myObject.func();
前面兩個輸出沒有問題,都是 bar,問題出在後面兩個。用了 IIFE 後,匿名函數內的 this 其實已經指到了 window,所以第三個輸出 this.foo 其實是 window.foo,而全域對象並沒有 foo 這個 key,所以輸出 undefined,而第四個輸出,因為 self 引用了 myObject,所以還是 bar。 四
What is the significance of, and reason for, wrapping the entire content of a JavaScript source file in a function block?
為什麼要用 IIFE。
簡單來說就是為了能模組化,建立私人變數等等,很多類庫(比如 jQuery)都用了這樣的寫法。
可以參考我以前翻譯的一篇文章 詳解javascript立即執行函數運算式(IIFE) 五
What is the significance, and what are the benefits, of including 'use strict' at the beginning of a JavaScript source file?
strict 模式下進行 Javascript 開發有啥好處。
這個就不展開來了,可以參考阮一峰老師的 Javascript strict 模式詳解 或者自行Google百度。 六
Consider the two functions below. Will they both return the same thing? Why or why not?
function foo1(){ return { bar: "hello" };}function foo2(){ return { bar: "hello" };}
執行以上兩個函數,會返回相同的東西嗎。
不會,第二個函數會返回 undefined。這是由於 Javascript 的封號插入機制決定的,如果某行代碼,return 關鍵詞後沒有任何東西了,將會自動插入一個封號,顯然 foo2 函數中,當 return 後被插入一個封號後,儘管後面的語句不符合規定,但是因為沒有執行到,所以也不會報錯了。沒有 return 任何東西的函數,預設返回 undefined。
所以很多 Javascript 規範建議把 { 寫在一行中,而不是另起一行。 七
What is NaN? What is its type? How can you reliably test if a value is equal to NaN?
NaN 是什麼鬼。typeof 的結果是。如果一個變數的值是 NaN,怎麼確定。
NaN 是 'not a number' 的縮寫,表示 "不是一個數字",通常會在運算過程中產生:
console.log('abc' / 4);console.log(4 * 'a');
雖然它 "不是一個數字",但是 NaN 的 typeof 結果卻是 number:
console.log(typeof (4 * 'a')); // number
NaN 和任何變數都不相等,包括 NaN 自己:
console.log(NaN === NaN); // false
判斷一個變數是不是 NaN 可以用 isNaN() 函數,但是這 並不是一個完美的函數,有些時候用 value !== value 似乎更準確,幸運的是,ES6 已經有 Number.isNaN() 方法,將比 isNaN() 準確的多。 八
What will the code below output? Explain your answer.
console.log(0.1 + 0.2);console.log(0.1 + 0.2 == 0.3);
上面代碼的輸出結果是什麼。
這個問題正好我之前研究過,有興趣的可以參考下 【0.1 + 0.2 = 0.30000000000000004】該怎樣理解。,看懂了還有興趣的可以看下這篇 玉伯的一道課後題題解(關於 IEEE 754 雙精確度浮點型精度損失) 九
Discuss possible ways to write a function isInteger(x) that determines if x is an integer.
寫一個方法 isInterger(x),可以用來判斷一個變數是否是整數。
ES6 中內建了 Number.isInteger() 方法。但是目前 ES5 中沒有內建的方法,可以把一個數去掉小數點後和原數進行比較,判斷是否相等,那麼問題就演變成如何對一個數進行取整了。
var a = -1.2223; console.log(a ^ 0); // -1 console.log(a | 0); // -1 console.log(a << 0); // -1 console.log(a >> 0); // -1 console.log(Math.round(a)); // -1 console.log(Math.floor(a)); // -2 console.log(Math.ceil(a)); // -1
十
In what order will the numbers 1-4 be logged to the console when the code below is executed? Why?
(function() { console.log(1); setTimeout(function(){console.log(2)}, 1000); setTimeout(function(){console.log(3)}, 0); console.log(4);})();
以上代碼的輸出結果是。
這題不難,只要知道 Javascript 是單線程的語言, 一些非同步事件是在主體 js 執行完之後執行即可,所以主體的 1、4 先輸出,而後是 3、2,沒有問題,因為 3 的定時設定比 2 早。
具體可以參考我之前的文章 從setTimeout談JavaScript運行機制 十一
Write a simple function (less than 80 characters) that returns a boolean indicating whether or not a string is a palindrome.
判斷一個字串是不是迴文。
function isPalindrome(str) { str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join(''));}
這裡想到一個進階題,求字串最長迴文子串,可以參考 求最長迴文子串 - leetcode 5. Longest Palindromic Substring 十二
Write a sum method which will work properly when invoked using either syntax below.
console.log(sum(2,3)); // Outputs 5console.log(sum(2)(3)); // Outputs 5
寫一個 sum 方法,使得以上代碼得到預期結果。這題可以參考我以前的文章 湯姆大叔的6道javascript編程題題解 中的最後一題,理論上此題更簡單,因為它沒要求能擴充(比如 sum(2)(3)(4)),甚至可以這樣:
function sum(x) { if (arguments.length == 2) { return arguments[0] + arguments[1]; } else { return function(y) { return x + y; }; }}
或者這樣:
function sum(x, y) { if (y !== undefined) { return x + y; } else { return function(y) { return x + y; }; }}
十三
Consider the following code snippet:
for (var i = 0; i < 5; i++) { var btn = document.createElement('button'); btn.appendChild(document.createTextNode('Button ' + i)); btn.addEventListener('click', function(){ console.log(i); }); document.body.appendChild(btn);}
(a) What gets logged to the console when the user clicks on “Button 4” and why?
(b) Provide one or more alternate implementations that will work as expected.
點擊 'Button 4' 後輸出什麼。如何使得輸出能跟預期相同。
答案是輸出 5,事實上點擊任意的 button,輸出都是 5。因為迴圈結束後,i 值變成了 5。如何改,使得輸出分別是 0, 1, 2, 3, 4。用閉包在記憶體中儲存變數,可以參考我之前的文章 這10道javascript筆試題你都會麼 中的第 8 題。 十四
What will the code below output to the console and why?
var arr1 = "john".split('');var arr2 = arr1.reverse();v