前些天寫js遇到了一個instanceof的坑,我們的頁面中有一個iframe,我在index頁面中計算得到了一個array,然后需要傳遞到Flight頁面
這個嵌套的iframe中的一個函數(SearchFlight)中,作為防御性編程,我需要在SearchFlight函數中進行參數檢測,也就是判斷過來的參數一
定是Array類型。
一:拋出問題
舉個例子,下面有兩個頁面。
Index.html頁面
1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <title></title>
5 </head>
6 <body>
7
8 <iframe name="childframe" src="Flight.html"></iframe>
9
10 <script type="text/javascript">
11
12 window.onload = function () {
13 //航班
14 var airplanes = ["MU", "CA", "CZ"];
15
16 var result = window.frames[0].flight.SearchFlight(airplanes);
17 };
18 </script>
19 </body>
20 </html>
Flight.html頁面
1 <!DOCTYPE html>
2 <html xmlns="http://www.w3.org/1999/xhtml">
3 <head>
4 <title></title>
5 </head>
6 <body>
7 <script type="text/javascript">
8
9 var flight = (function () {
10
11 return {
12 SearchFlight: function (arr) {
13 var result = arr instanceof Array;
14 alert(result);
15 }
16 };
17 })();
18 </script>
19 </body>
20 </html>

很驚訝的發現instanceof居然不能判斷出arr是一個數組,其實我們用肉眼可以看到,壓根它就是一個數組,但是為什么instanceof卻判斷不出來呢?
我們知道instancof其實是一個js語法糖,我就修改成簡單點的,判斷arr.constructor是否指向Array,於是我把關鍵字改成如下形式,再來看看看效果。
1 var flight = (function () {
2
3 return {
4 SearchFlight: function (arr) {
5 //var result = arr instanceof Array;
6
7 var result = arr.constructor == Array;
8
9 alert(result);
10 }
11 };
12 })();

從圖上看,還真有點奇怪,明明都是function Array(),為啥都不能相等呢?不過事實就擺在眼前,容不得狡辯,只能靜下心來想一想,我們
知道Array在js是屬於引用類型,既然不相等那就說明他們其實是兩個引用,對不對,並且Array是掛在window下的一個屬性,window屬性
也就是一個窗口的實例,那就說明Index.html是一個window實例,Flight.html也是一個window實例,為了驗證下,我們看看兩個window
是否相等?

看完圖后,答案就很明白了,以C#的思維考慮一下,既然大的window都不相等,里面的Array屬性自然就不相等,終於問題是找到了,下面
怎么解決呢?
二:解決問題
1. length判斷
這個很容易想到,也是最簡單的,我們知道每個數組都有length,所以可以簡簡單單的看length是否存在就可以了,但是這個也不是萬無一失
的,我們知道function中有兩個屬性length和prototype,那這就有問題了。這樣我會錯誤的把f認為是數組。

2.使用prototype的call方法來實現
這個方法有點巧妙,首先我們要知道,每一個function中都會有call方法和prototype屬性,而js在Object.prototype中的tostring函數上做了一個
封裝,就是調用tostring.call后,會返回[object constructorName]的字符串格式,這里的constructorName就是call參數的函數名,比如我們把
arr傳進去,就會返回“[object Array]”字符串格式,這個方法也可以讓我們巧妙的判斷是否是Array,但是比較遺憾的是,我們看不到這個call的內
部實現,只能黑盒的記住了。


