Javascript中判斷陣列的正確姿勢

發表於2016-01-06

在 Javascript 中,如何判斷一個變數是否是陣列?

最好的方式是用 ES5 提供的 Array.isArray() 方法(畢竟原生的才是最屌的):

但是鑑於低版本 IE 不支援 ES5,如需相容,需要想想別的辦法。

typeof

我們都知道,陣列是特殊的物件,所以陣列的 typeof 結果也是 object,而因為 null 的結果也是 object,所以如需用 typeof 運算子來判斷陣列,需要這麼寫:

instanceof

來回憶下 instanceof 運算子的使用方式。a instanceof b,如果返回 true,表示 a 是 b 的一個例項。那麼如果 a instanceof Array 返回 true,是不是就說明 a 是 陣列型別呢?跟 instanceof 師出同門的還有 constructor,是否同樣可以判斷呢?

答案是否定的,需要注意巢狀 frame 的情況。

index.htm 程式碼:

a.htm 程式碼:

我們看到 index.htm 程式碼中,變數 a 確實是一個陣列,但是 a instanceof Array 的結果卻是 false。

這是因為每個 frame 都有一套自己的執行環境,跨 frame 例項化的物件彼此不共享原型鏈。如果列印 a instanceof window.frames[0].Array,那麼結果就是 true 了。

特性嗅探?

也不靠譜,萬一某個物件正好有值為 sort 的 key 呢?

正確的姿勢是使用 Object.prototype.toString() 判斷:

事實上,這也是一些類庫進行陣列(甚至其他型別)判斷的主流方式。

比如在 jQuery 中進行陣列判斷的相關程式碼(PS:摘自 jQuery 1.10.1,最近版本的 jQuery 只保留了 Array.isArray(),沒有對不支援 ES5 的瀏覽器做相容):

程式碼很清晰,如支援原生的 Array.isArray(),則直接判斷,不支援的話呼叫 toString() 進行判斷。同時可以看到很多其他型別變數的判斷也是基於 toString() 方法。當然這裡說的 toString() 均是 Object 原型鏈上的 toString() 方法。

Object.prototype.toString() 為何能返回這樣型別的字串?

ECMA-262:

上面的規範定義了 Object.prototype.toString 的行為:首先,取得物件的一個內部屬性[[Class]],然後依據這個屬性,返回一個類似於 “[object Array]” 的字串作為結果([[]]用來表示語言內部用到的、外部不可直接訪問的屬性,稱為 “內部屬性”)。利用這個方法,再配合 call,我們可以取得任何物件的內部屬性 [[Class]],然後把型別檢測轉化為字串比較,以達到我們的目的。還是先來看看在 ECMA 標準中 Array 的描述吧:

所以 Javascript 中判斷陣列的函式可以這樣寫:

Read More:

相關文章