传统方案
1. Object.prototype.toString.call 方法
原理 :通过调用 Object.prototype.toString.call(obj) ,判断返回值是否为 [object Array] 。
js
function isArray(obj){
return Object.prototype.toString.call(obj) === '[object Array]';
}
缺陷:
-
ES6 引入
Symbol.toStringTag后,可被人为篡改。例如:jsconst obj = { [Symbol.toStringTag]: 'Array' }; console.log(Object.prototype.toString.call(obj)); // 输出 [object Array] -
若开发通用型代码(如框架、库),该漏洞会导致判断失效。
2. instanceof 方法
原理 :判断对象原型链上是否存在 Array 构造函数。
js
function isArray(obj){
return obj instanceof Array;
}
缺陷:
-
可通过
Object.setPrototypeOf篡改原型链,导致误判。例如:jsconst obj = {}; Object.setPrototypeOf(obj, Array.prototype); console.log(obj instanceof Array); // 输出 true,但 obj 并非真正数组 -
跨 iframe 场景失效。不同 iframe 中的
Array构造函数不共享,导致真数组被误判为非数组。例如:jsconst frame = document.querySelector('iframe'); const Array2 = frame.contentWindow.Array; const arr = new Array2(); console.log(arr instanceof Array); // 输出 false,但 arr 是真正数组
ES6 原生方法
方法 :使用 Array.isArray 静态方法。
js
console.log(Array.isArray(arr));
优势:
-
该方法由JavaScript引擎内部实现,直接判断对象是否由 Array 构造函数创建,不受原型链、 Symbol.toStringTag 或跨 iframe 影响;
-
完美解决所有边界场景。
总结
判断数组的方法中 Array.isArray 是唯一准确且无缺陷的方案。其他方法(如Object.prototype.toString.call、instanceof)均存在局限性,仅在特定场景下可用。