在 JavaScript 中,由于数组本质上是对象,使用 typeof
无法准确判断数组类型(typeof []
返回 "object"
)。因此,需要使用更可靠的方法来判断一个变量是否为数组。
以下是几种常用且推荐的方法,按优先级排序:
✅ 方法 1:Array.isArray()
(推荐)
ES5 引入的 Array.isArray()
是最直接、最可靠的判断方法。
Array.isArray([]) // true
Array.isArray([1, 2, 3]) // true
Array.isArray(new Array()) // true
Array.isArray({}) // false
Array.isArray("array") // false
Array.isArray(null) // false
Array.isArray(undefined) // false
优点:
- 语义清晰,专为判断数组设计。
- 性能高。
- 不受原型链或跨上下文环境(如 iframe)影响。
兼容性:现代浏览器和 Node.js 都支持。对于旧环境,可使用 polyfill。
✅ 方法 2:Object.prototype.toString.call()
利用 toString()
的内部行为,可以准确获取对象的“内部 [[Class]]”标签。
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call({}) // "[object Object]"
Object.prototype.toString.call(new Date()) // "[object Date]"
// 判断数组
function isArray(value) {
return Object.prototype.toString.call(value) === '[object Array]';
}
isArray([1, 2]); // true
优点:
- 非常可靠,不受对象原型修改的影响。
- 可用于判断其他内置对象类型(如
Date
,RegExp
)。
缺点:
- 代码稍长,不够直观。
⚠️ 方法 3:instanceof Array
[] instanceof Array // true
[1, 2] instanceof Array // true
问题:
- 在跨 iframe 或跨窗口环境中会失效,因为不同全局环境中的
Array
构造函数不同。
// 假设 arr 来自另一个 iframe
const arr = window.frames[0].Array(1, 2);
arr instanceof Array; // false!
- 如果
Array
构造函数被修改,也可能出错。
结论:不推荐在可能跨上下文的场景中使用。
❌ 不推荐的方法
1. typeof
(完全无效)
typeof [] === "object" // true,但无法区分对象和数组
2. 检查 length
属性或数组方法
// 错误!对象也可以有 length 属性
const fakeArray = { length: 0 };
"length" in value && typeof value.length === "number" // 不能保证是数组
// 错误!方法可能被模拟
value.push && typeof value.push === "function" // 不可靠
3. constructor
属性
[].constructor === Array // true
// 但 constructor 可能被修改或不存在
const obj = Object.create(null);
obj.constructor = Array;
// obj 不是数组,但检查会通过
总结
方法 | 是否推荐 | 说明 |
---|---|---|
Array.isArray(value) | ✅ 强烈推荐 | 最标准、最安全的方法 |
Object.prototype.toString.call(value) === '[object Array]' | ✅ 推荐 | 可靠,适用于需要兼容旧环境或判断多种类型 |
value instanceof Array | ⚠️ 谨慎使用 | 在单全局环境且 Array 未被修改时可用,但有跨上下文问题 |
typeof , length , constructor 等 | ❌ 不推荐 | 不可靠或易被欺骗 |
最佳实践:
- 优先使用
Array.isArray()
。 - 在需要支持非常旧的 JavaScript 环境时,使用
Object.prototype.toString.call()
作为 fallback。 - 避免使用
instanceof Array
,除非你完全控制运行环境。
THE END