好程序員Java教程分享JavaScript常見面試題一程序員
好程序員Java教程分享JavaScript常見面試題一:1.使用 typeof bar === "object" 來肯定 bar 是不是對象的潛在陷阱是什麼?如何避免這個陷阱?面試
儘管 typeof bar === "object" 是檢查 bar 是否對象的可靠方法,使人驚訝的是在JavaScript中 null 也被認爲是對象!數組
所以,令大多數開發人員驚訝的是,下面的代碼將輸出 true (而不是false) 到控制檯:閉包
var bar = null;console.log(typeof bar === "object"); // logs true!ide
只要清楚這一點,同時檢查 bar 是否爲 null,就能夠很容易地避免問題:函數
console.log((bar !== null) && (typeof bar === "object")); // logs falsethis
要答全問題,還有其餘兩件事情值得注意:spa
首先,上述解決方案將返回 false,當 bar 是一個函數的時候。在大多數狀況下,這是指望行爲,但當你也想對函數返回 true 的話,你能夠修改上面的解決方案爲:插件
console.log((bar !== null) && ((typeof bar === "object") || (typeof bar === "function")));code
第二,上述解決方案將返回 true,當 bar 是一個數組(例如,當 var bar = [];)的時候。在大多數狀況下,這是指望行爲,由於數組是真正的對象,但當你也想對數組返回 false 時,你能夠修改上面的解決方案爲:
console.log((bar !== null) && (typeof bar === "object") && (toString.call(bar) !== "[object Array]"));
或者,若是你使用jQuery的話:
console.log((bar !== null) && (typeof bar === "object") && (! $.isArray(bar)));
2.下面的代碼將輸出什麼到控制檯,爲何?
(function(){ var a = b = 3;
})(); console.log("a defined? " + (typeof a !== 'undefined'));console.log("b defined? " + (typeof b !== 'undefined'));
因爲 a 和 b 都定義在函數的封閉範圍內,而且都始於 var關鍵字,大多數JavaScript開發人員指望 typeof a 和 typeof b 在上面的例子中都是undefined。
然而,事實並不是如此。這裏的問題是,大多數開發人員將語句 var a = b = 3; 錯誤地理解爲是如下聲明的簡寫:
var b = 3;var a = b;
但事實上,var a = b = 3; 實際是如下聲明的簡寫:
b = 3;var a = b;
所以(若是你不使用嚴格模式的話),該代碼段的輸出是:
a defined? falseb defined? true
可是, b 如何才能被定義在封閉函數的範圍以外呢?是的,既然語句 var a = b = 3; 是語句 b = 3; 和 var a = b;的簡寫, b 最終成爲了一個全局變量(由於它沒有前綴 var 關鍵字),所以仍然在範圍內甚至封閉函數以外。
須要注意的是,在嚴格模式下(即便用 use strict),語句var a = b = 3; 將生成ReferenceError: b is not defined的運行時錯誤,從而避免任何不然可能會致使的headfakes /bug。 (仍是你爲何應該理所固然地在代碼中使用 use strict 的最好例子!)
3.下面的代碼將輸出什麼到控制檯,爲何?
var myObject = {
foo: "bar",};
myObject.func();
上面的代碼將輸出如下內容到控制檯:
outer func: this.foo = bar
outer func: self.foo = bar
inner func: this.foo = undefined
inner func: self.foo = bar
在外部函數中, this 和self 二者都指向了 myObject,所以二者均可以正確地引用和訪問 foo。
在內部函數中, this 再也不指向 myObject。其結果是,this.foo 沒有在內部函數中被定義,相反,指向到本地的變量self 保持在範圍內,而且能夠訪問。 (在ECMA 5以前,在內部函數中的this 將指向全局的 window 對象;反之,由於做爲ECMA 5,內部函數中的功能this 是未定義的。)
4.封裝JavaScript源文件的所有內容到一個函數塊有什麼意義及理由?
這是一個愈來愈廣泛的作法,被許多流行的JavaScript庫(jQuery,Node.js等)採用。這種技術建立了一個圍繞文件所有內容的閉包,也許是最重要的是,建立了一個私有的命名空間,從而有助於避免不一樣JavaScript模塊和庫之間潛在的名稱衝突。
這種技術的另外一個特色是,容許一個易於引用的(假設更短的)別名用於全局變量。這一般用於,例如,jQuery插件中。jQuery容許你使用jQuery.noConflict(),來禁用 $ 引用到jQuery命名空間。在完成這項工做以後,你的代碼仍然可使用$ 利用這種閉包技術,以下所示:
(function($) { /* jQuery plugin code referencing $ */ } )(jQuery);