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