JS精準判斷一個對象是不是數(shù)組的方法
為什么判斷數(shù)組這么難?
在 JavaScript 中,數(shù)組本質(zhì)上也是一種對象。
console.log(typeof []); // "object"
console.log(typeof {}); // "object"
因為 typeof 只能區(qū)分基本類型(string, number, boolean, undefined, symbol, bigint)和引用類型(統(tǒng)一返回 object,函數(shù)返回 function),所以它無法直接告訴我們:“嘿,這是個數(shù)組!”
我們需要更高級的手段來揭開它的真面目。
1. 王者方案:Array.isArray()
這是 ES5 引入的標準方法,也是現(xiàn)代開發(fā)中的首選。
console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray("hello")); // false
console.log(Array.isArray(null)); // false
優(yōu)點
- 語義清晰:代碼可讀性極高,一眼就能看懂意圖。
- 準確可靠:內(nèi)部實現(xiàn)機制完善,能正確處理各種邊界情況。
- 跨上下文安全:即使數(shù)組來自不同的 iframe 或 window,它依然能正確識別(因為它不依賴原型鏈繼承關(guān)系,而是檢查內(nèi)部標簽)。
缺點
- 兼容性:不支持 IE8 及以下版本(但在 2024 年,這幾乎不再是問題)。
博主建議:
無腦選它! 除非你有極其特殊的兼容需求,否則 Array.isArray 就是你的唯一選擇。
2. 經(jīng)典方案:instanceof
instanceof 運算符用于檢測構(gòu)造函數(shù)的 prototype 屬性是否出現(xiàn)在某個實例對象的原型鏈上。
const arr = [];
console.log(arr instanceof Array); // true
const obj = {};
console.log(obj instanceof Array); // false
優(yōu)點
- 直觀:符合面向?qū)ο缶幊痰乃季S邏輯,“這個實例是不是由 Array 構(gòu)造函數(shù)創(chuàng)建的?”
缺點
跨上下文失效:這是最大的坑!
如果頁面中有多個 iframe,每個 iframe 都有自己獨立的執(zhí)行環(huán)境(也就是獨立的 Array 構(gòu)造函數(shù))。
// 假設(shè) iframe 中的數(shù)組傳到了主窗口 iframeArray instanceof Array; // false! // 因為 iframeArray 的原型鏈指向的是 iframe 里的 Array.prototype, // 而主窗口里的 Array 是另一個構(gòu)造函數(shù)。
- 可被篡改:如果開發(fā)者手動修改了原型鏈,
instanceof可能會給出錯誤結(jié)果。
3. 通用方案:Object.prototype.toString
這是一種“黑科技”寫法,利用對象內(nèi)部的 [[Class]] 屬性(在 ES5 之前稱為 Class 內(nèi)部屬性,現(xiàn)在通過 toString 暴露)。
const arr = [];
console.log(Object.prototype.toString.call(arr)); // "[object Array]"
const obj = {};
console.log(Object.prototype.toString.call(obj)); // "[object Object]"
const str = "hello";
console.log(Object.prototype.toString.call(str)); // "[object String]"
優(yōu)點
- 萬能 鑰匙:不僅能判斷數(shù)組,還能精準判斷
Date,RegExp,Function,Null,Undefined等所有內(nèi)置類型。 - 跨上下文安全:和
Array.isArray一樣,它不受不同 window/iframe 的影響,因為它讀取的是底層引擎標記。
缺點
- 寫法繁瑣:
Object.prototype.toString.call(obj)太長,容易寫錯。 - 可讀性差:新手可能看不懂這是在干嘛。
技巧:
你可以封裝一個工具函數(shù):
const typeCheck = (obj) => Object.prototype.toString.call(obj).slice(8, -1); console.log(typeCheck([])); // "Array"
4. 避坑指南:typeof與constructor
陷阱 1:typeof
如前所述,typeof [] 返回 "object",完全無法區(qū)分數(shù)組和普通對象。千萬別用!
陷阱 2:constructor
const arr = []; console.log(arr.constructor === Array); // true
看起來不錯?但它有兩個致命弱點:
可被修改:arr.constructor 是可以被人為賦值的,不可信。
arr.constructor = String; console.log(arr.constructor === Array); // false (誤判!)
null/undefined 報錯:null 和 undefined 沒有構(gòu)造函數(shù),訪問會報錯。
5. 跨框架/跨窗口場景的特殊陷阱
這是高級前端面試的???。
場景:你的主頁面嵌入了一個 iframe,iframe 里有一個數(shù)組 iframeArr,你把它傳回主頁面。
| 方法 | 結(jié)果 | 原因 |
|---|---|---|
iframeArr instanceof Array | ? False | 主頁面的 Array 和 iframe 的 Array 不是同一個引用。 |
Array.isArray(iframeArr) | ? True | 規(guī)范規(guī)定它檢查內(nèi)部插槽,不依賴原型鏈。 |
Object.prototype.toString.call(iframeArr) | ? “[object Array]” | 同樣基于內(nèi)部標簽,不受上下文影響。 |
結(jié)論:
在涉及多窗口、Web Worker 或微前端架構(gòu)時,嚴禁使用 instanceof 判斷數(shù)組,必須使用 Array.isArray 或 toString 方法。
6. 總結(jié)與最佳實踐
| 方法 | 準確性 | 跨上下文安全 | 可讀性 | 推薦指數(shù) |
|---|---|---|---|---|
Array.isArray() | ????? | ? 是 | ????? | ?????????? |
Object.prototype.toString | ????? | ? 是 | ?? | ?????? |
instanceof | ??? | ? 否 | ???? | ???? |
constructor | ?? | ? 否 | ??? | ? 不推薦 |
typeof | ? 無效 | - | ????? | ? 禁止使用 |
博主寄語:
判斷數(shù)組看似簡單,實則暗藏玄機。
記住一條鐵律:
永遠優(yōu)先使用 Array.isArray()。
它不僅是最標準的 API,也是最安全、最易讀的選擇。
只有在需要同時判斷多種類型(如寫一個通用的 typeOf 工具庫)時,才考慮使用 Object.prototype.toString。
以上就是JS精準判斷一個對象是不是數(shù)組的方法的詳細內(nèi)容,更多關(guān)于JS判斷對象是不是數(shù)組的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript實現(xiàn)網(wǎng)頁截圖功能
這篇文章主要介紹了JavaScript實現(xiàn)網(wǎng)頁截圖功能,本文介紹了2款實現(xiàn)JavaScript截圖的開源組件,一個是Canvas2Image,一個是html2canvas,需要的朋友可以參考下2014-10-10

