|
|
|
|
|
“數(shù)組是類似列表的對象,其原型具有執(zhí)行遍歷和變異操作的方法。” — MDN 文檔
如何在 JavaScript 中檢查對象是否數(shù)組?本文將詳細(xì)介紹 5 種方法,并比較它們的優(yōu)缺點:
方法一:Array.isArray([])
ECMAScript 5 (ES5) 引入了 Array.isArray()
方法來檢查數(shù)組,因為 typeof
無法將數(shù)組與其他對象區(qū)分開來,例如內(nèi)置對象 Date
和 RegExp
。
使用 Array.isArray()
也有助于確保我們的對象不為空,因為由于長期存在的錯誤,null
具有“對象”類型。
下面是使用 Array.isArray([])
檢查數(shù)組的示例:
方法二:Object.prototype.toString.call([])
冗長的 JavaScript 語句 Object.prototype.toString.call()
可以區(qū)分?jǐn)?shù)組和其他類型的對象,因為它返回的字符串比 typeof
更詳細(xì)地指定了對象類型。
因為此方法適用于任何對象,所以我稱其為 JavaScript 中類型檢查的最佳方法。這是一個例子:
雖然冗長,但此方法適用于任何原始類型和任何對象。它總是返回變量的構(gòu)造函數(shù)的名稱。
換句話說,Object.prototype.toString.call()
有點像 instanceof
的逆向,盡管它在 iframe 中運行良好。
上述 isArray()
函數(shù)的行為應(yīng)該與內(nèi)置的 Array.isArray()
函數(shù)相同。
這里要注意的一點是 typeof {}
返回“object
”(小寫),但 Object.prototype.toString.call({}).slice(8,-1)
返回“Object
”(大寫)對象 {}
和數(shù)組 []
的“Array
”(大寫)。
與所有這些方法一樣,如果尚未聲明變量,此方法將不起作用。稍后我將討論檢查未聲明的變量。
方法三:[] instanceof 數(shù)組
使用關(guān)鍵字 instanceof
可用于檢查數(shù)組或任何類型的 JavaScript 對象。
“instanceof 運算符測試構(gòu)造函數(shù)的原型屬性是否出現(xiàn)在對象原型鏈的任何位置。” — MDN 文檔
語法很簡單,如下代碼示例所示:
但請注意,iframe 可能會破壞這種行為,如 Mozilla 開發(fā)人員網(wǎng)絡(luò)文檔中 Array.isArray
中所述:
instanceof vs isArray
在檢查 [an] Array 實例時,Array.isArray
優(yōu)于instanceof
,因為它通過 iframe 工作。— MDN 文檔
這意味著我們可能根本不想使用 instanceof
來檢查數(shù)組,以防萬一我們的 JavaScript 代碼最終在 iframe 中運行。
方法四:[].constructor
這是一個類似于 instanceof
的方法——調(diào)用 JavaScript 對象的 .constructor
屬性。
.constructor
屬性將返回構(gòu)造函數(shù),對于數(shù)組,它是函數(shù) Array()
(即 JavaScript 類 Array
)。
訪問該函數(shù)的 .name
屬性將給出字符串“Array”,該字符串可用于形成對數(shù)組是否存在的簡單檢查。
由于 .constructor
屬性返回函數(shù) Array()
(即 JavaScript 類 Array
),因此也可以直接將其與全局 Array
對象(即返回的函數(shù) Array()
所引用的對象)進(jìn)行比較。
換句話說,實際上不必使用 .name
屬性:[].constructor===Array
等價于 [].constructor.name==="Array"
。
這是一個代碼示例:
與 Object.prototype.toString.call()
類似,訪問 .constructor
屬性將適用于任何類型的 JavaScript 值,包括原語——盡管您不能訪問 .constructor
以獲取未定義或空值。
(請注意,instanceof
關(guān)鍵字適用于對象,但不適用于基元。當(dāng)然,instanceof
在 iframe 中存在錯誤。)
正如我們在上面看到的,使用沒有 null
檢查的 .constructor
會導(dǎo)致 null 和 undefined 的 TypeError
— 與 Array.isArray()
相比的缺點,后者只會為這兩個值返回 false。
并且,與到目前為止介紹的任何方法一樣,如果想嘗試訪問未聲明的變量,它們將引發(fā) ReferenceError
。
.constructor
是可變的在繼續(xù)之前,值得注意的是 .constructor
并不健壯,因為它是一個可以在以后覆蓋的對象屬性。
請記住,如果你出于任何原因通過原型覆蓋您的構(gòu)造函數(shù),則 arr.constructor === Array
測試將返回 false
。Array.isArray(arr)
仍然返回 true
。
所以只要記住一個對象的 .constructor
屬性是“可變的”——它可能已經(jīng)在代碼中的某個地方從它的原始值改變了。
方法 5:&& 和 [].constructor(空檢查?。?/span>
這是一個簡潔的單行代碼,它將在檢查數(shù)組的同時檢查非空值:[] && [].constructor === Array
。
null
和 undefined
都是false
,這意味著它們在條件語句中評估為false
,但所有對象都是true
,包括空數(shù)組。檢查 [] && [].constructor === Array
將為 null
或未定義的值返回 false
,而單獨的 .constructor
會引發(fā)錯誤。
包含邏輯 AND (&&)
運算符的優(yōu)點是可以避免由于 null
和 undefined
沒有屬性而發(fā)生的 TypeError
。這是有效的,因為 &&
是一個“短路運算符”。通過使用邏輯 AND (&&)
,我們在嘗試訪問 .constructor
屬性之前檢查該值是否為true
。這是一個代碼示例:
為了提高代碼的可讀性,你可以考慮使用松散相等(==
)來顯式地檢查空值:[] != null && [].constructor
。使用 !=
(松散相等運算符)意味著 null
和 undefined
彼此相等。
更明確的檢查將使用嚴(yán)格相等:[] !== null && [] !== undefined && [].constructor === Array
。許多 JavaScript 程序員寧愿從不使用松散相等,因為 ==
的規(guī)則令人困惑。
使用 && 和 .constructor
對 null
和 undefined
的工作方式與 Array.isArray()
的效果相同:它返回 false
,正如你所希望的那樣。
但是,未聲明的變量在嘗試訪問 .constructor
屬性時仍會引發(fā) ReferenceError
。你可以在數(shù)組檢查之前使用 typeof
檢查該值是否“undefined
”以解決該問題。
如果數(shù)組變量實際上是未聲明的怎么辦?
你可能不確定是否實際上已經(jīng)聲明了可能是數(shù)組的變量。讓我簡單談?wù)剻z查未聲明的數(shù)組。
提醒一下,訪問尚未聲明的變量將引發(fā) ReferenceError
,而已聲明但未分配特定值的變量將具有 undefined
值。
值得慶幸的是,typeof
關(guān)鍵字將為尚未聲明的變量返回“undefined
”,與未定義的值相同,但不會拋出 ReferenceError
,因為該變量還沒有被聲明。
這意味著我們可以將 Array.isArray()
包裝在 typeof
調(diào)用中,以使其對未聲明的變量具有魯棒性。這是一個例子:
或者,我們可以使用 try...catch
塊來捕獲潛在的 ReferenceError
,但 typeof
對未聲明的變量同樣有效。
如何在 JavaScript 中檢查空數(shù)組?
相反,如果我們想檢查一個數(shù)組是否為空,我們可以檢查它的 .length
屬性——一個空數(shù)組的 .length
為 0。
同樣,我們需要確保我們正在使用一個已聲明的變量,該變量已經(jīng)分配了一個絕對是數(shù)組的值。
但是,假設(shè)我們從 Array.isArray([])
得到 true
,那么 [].length > 0
將確認(rèn)我們的數(shù)組不為空。這是一個代碼片段:
同樣,我們正在利用 &&
作為短路運算符。因為它在錯誤陳述上“短路”,所以我們永遠(yuǎn)不會達(dá)到上面示例中的 .length
調(diào)用。這正是我們想要的,因為 .length
不適用于大多數(shù)原語,如數(shù)字或其他類型的對象。
總結(jié)
本文詳細(xì)介紹了5 種不同的檢查 JavaScript 數(shù)組的方法。我在編碼時通常使用 Array.isArray()
,有幾個原因:
有時,在我擔(dān)心未聲明變量的罕見情況下,我會將數(shù)組檢查包含在 if(typeof !== "undefined")
語句中。
參考文章