DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> JS教程:數組類型檢測和集合檢測
JS教程:數組類型檢測和集合檢測
編輯:關於JavaScript     

Question:編寫一個函數 isArray(testVar) 。當testVar是數組類型時,返回1;當testVar是集合時,返回2;其他情況返回0。

Solution:

一、數組類型檢測

(1)檢測構造函數

本來這應該是最簡單的事情,Javascript中提供了instanceof運算符,可以檢測某個變量是否某種類型的實例,一般情況下可以這樣檢測數組:testVar instanceof Array == true。但是,在跨frame的時候,等式不成立。假設測試頁test.html的代碼如下:

<script language=”javascript” type=”text/javascript”>
//<![CDATA[
function isArray(testVar) {
 return testVar instanceof Array;
}
//]]>
</script>
<iframe id=”testFrame” src=”testframe.html”></iframe>

testframe.html的代碼如下:

<script language=”javascript” type=”text/javascript”>
//<![CDATA[
function isArray(testVar) {
 alert(parent.isArray([]));
}
//]]>
</script>

輸出的內容是false。似乎每個頁面都有自己的Array類型,如果把isArray改寫一下,輸出的就是true:

function isArray(testVar) {
 return testVar instanceof document.getElementById(”testFrame”).contentWindow.Array;
}

檢測testVar.constructor也會出現類似的情況。因此,這種方法不可行。

(2)檢測特性

通過數組獨有的函數進行檢測,比如檢測testVar.sort是否未定義。這種方法在一般情況下也是可行的,但是健壯性不足。如果給testVar動態加了一個sort方法,判斷就會失誤。

(3)jQuery1.3帶來了曙光

沒什麼好說的,直接看代碼,太牛了:

if (Object.prototype.toString.call(testVar) === “[object Array]“) return 1;

二、集合檢測

所謂的集合就是可以通過下標訪問但又不是數組的類型。已知的Javascript集合有兩種,一種是HtmlCollection,另一種是函數的參數arguments

(1)排他法

在已知testVar不是數組的情況下,先檢測它的length屬性是否存在。包含length屬性的類型也不少,比如window、String、某些HtmlElement。所以要檢測的特征非常多:

testVar.length != null &&
!testVar.alert && // 不是window
!testVar.charAt && // 不是String
!testVar.nodeType // 不是HtmlElement

由於其他情況實在太多,容易出現疏漏,所以最終還是沒有采取這種辦法。

(2)檢測特性

已知的集合只有兩種,所以還是檢查這兩種集合的特性吧。HtmlCollection有item方法,而arguments則有callee屬性:

if (testVar.item || testVar.callee) return 2;

這時,select元素開始攪局。它竟然包含HtmlCollectiond的所有特性。於是,還是要判斷nodeType:

if (!testVar.nodeType && testVar.item || testVar.callee) return 2;

select元素被轟走了,萬惡的ie開始搗亂。首先是XML的問題,某個ajax回調函數:

function onSuccess(xhr) {
var xmlDoc = xhr.responseText;
alert(xmlDoc.getElementsByTagName); // ie下報錯
var root = xmlDoc.getElementsByTagName(”root”);
alert(root.item) // ie下報錯
}

也就是說,在ie下,只要嘗試檢測xml節點或xml節點集合的方法都會報錯。幸好還可以用typeof去對付它們。

function onSuccess(xhr) {
var xmlDoc = xhr.responseText;
alert(typeof(xmlDoc.getElementsByTagName)); // ie下輸出”unknown”
var root = xmlDoc.getElementsByTagName(”root”);
alert(typeof(root.item)) // ie下輸出”unknown”
}

因此,代碼就改成:

if (!testVar.nodeType && typeof testVar.item != “undefined” || testVar.callee) return 2;

其次,是window對象的問題:ie下的window對象也有item方法。所以還是要檢測window對象:

if (!testVar.nodeType && typeof testVar.item != “undefined” && !testVar.alert || testVar.callee) return 2;

雖然檢測特性容易出現失誤,但是目前也只有這種辦法了。

至此,終於折騰完,整個函數簡寫後就是:

var isArray = function(testVar) {
 return Object.prototype.toString.call(testVar) === “[object Array]” ? 1 :  testVar.callee || (typeof testVar.item != “undefined” && !testVar.nodeType && !testVar.alert) ? 2 : 0;
};

目前還不知道有沒有疏漏。

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved