普通视图

发现新文章,点击刷新页面。
今天 — 2026年1月16日首页

为啥 Array.isArray 判断数组最靠谱?

2026年1月16日 11:12

JavaScript 中,如何判断一个值是否为数组是很常见的需求,一般有以下几种方法。

1、方式一:JSON.stringify

可以通过 JSON.stringify 序列化字符串,然后判断字符串是否以 [" 开头,以 "] 结尾来判断是否为数组。这其实和使用 JSON.stringify(obj) === '{}' 判断一个对象是否是空对象的思路类似。

const arr = [];
console.log(JSON.stringify(arr).startsWith('[') && JSON.stringify(arr).endsWith(']')); // true

优点

  • 兼容性好。

缺点

  • 需要序列化性能较差。
  • 无法处理循环引用的数据,会报错 TypeError: Converting circular structure to JSON
  • 判断代码也较为复杂。
const arr = [];
arr[0] = arr; // 添加循环引用
console.log(JSON.stringify(arr).startsWith('[') && JSON.stringify(arr).endsWith(']')); // 报错 TypeError: Converting circular structure to JSON

2、方式二:instanceof

instanceof 可以判断某个实例是否属于某种类型,它内部会通过原型链往上一级一级查找,直到找到和当前对象的原型相等的原型。

console.log([] instanceof Array);      // true
console.log({} instanceof Array);      // false

但是原型链是可以被修改的,所以 instanceof 判断结果可能不准确。比如我们可以利用 Object.setPrototypeOf(target, newProto) 来修改原型。

const arr = {};
Object.setPrototypeOf(arr, Array.prototype);
console.log(arr instanceof Array); // true

还有一种情况,就是跨 iframe 进行判断时,instanceof 判断结果可能不准确。

<!DOCTYPE html>
<html lang="en">

<body>
  <script>
    const iframe = document.createElement('iframe');
    document.body.appendChild(iframe);
    const iframeArray = iframe.contentWindow.Array;
    const iframeArr = new iframeArray();
    console.log(iframeArr instanceof Array);  // false
  </script>
</body>

</html>

这里其实 iframeArr 是一个数组,但是 instanceof 判断结果却是 false

优点

  • 简单直观。

缺点

  • 通过 Object.setPrototypeOf 修改原型后判断不准确。
  • iframe 失效。

3、方式三:constructor 属性

每个实例对象都有一个 constructor 属性,指向它的构造函数,所以通过 constructor 属性可以判断一个实例是否属于某个类型。

console.log([].constructor === Array);  // true
console.log({}.constructor === Array);  // false

然而和原型一样,constructor 属性也是可以被修改的。

const arr = [];
arr.constructor = Object; // 修改 constructor
console.log(arr.constructor === Array); // false(被修改了导致判断错误)

优点

  • 简单直观。

缺点

  • constructor 可被修改,判断不准确。

4、方式四:Object.prototype.toString.call

Object.prototype.toString.call()JavaScript 中一个非常强大的类型检测方法,它可以获取任意值的内部 [[Class]] 属性,并以字符串形式返回其类型。

const arr = [];
console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

它是一个检测数据类型的标准方法,它不仅可以检查数组 Array、对象 Object,基本数据类型和其它引用类型像日期 Date正则 regexp 等都可以判断出来,实际开发中通常会把它封装成一个通用的类型检测方法。

// 判断特定类型
function isType(value, type) {
    return Object.prototype.toString.call(value) === `[object ${type}]`;
}

console.log(isType([], 'Array'));     // true
console.log(isType({}, 'Object'));    // true
console.log(isType(new Date(), 'Date')); // true
console.log(isType(/abc/, 'RegExp')); // true

但是在 es6Symbol出现之后,可以通过 Symbol.toStringTag 属性来控制其返回值,也会导致其判断不准确。

const arr = {
  [Symbol.toStringTag]: 'Array'
}
console.log(Object.prototype.toString.call(arr) === '[object Array]'); // true

Symbol.toStringTag 也可以支持设置为任意值。

const obj = {
  [Symbol.toStringTag]: '111' // 可以设置为任意值
}
console.log(Object.prototype.toString.call(obj)); // [object 111]

优点

  • 简单直观。
  • 不仅可以判断数组,基本数据类型和其它引用数据类型 DateRegexp 也可以。

缺点

  • 代码较长,并且可通过 Symbol.toStringTag 修改判断结果。

5、方式五:Array.isArray(最推荐)

Array.isArray()Array 的一个静态方法,可以判断一个值是否为数组。

const arr = [];
console.log(Array.isArray(arr));  // true

优点

  • 最可靠。
  • 简单直观。

缺点

  • 兼容性问题,只支持 IE9+

为什么 Array.isArray 是最靠谱的呢?

1. 通过判断内部存储的数据结构是否符合数组的数据结构定义

数组是一种数据结构:

  • 它是一种线性表数据结构,也就是它里面的数据是排成一条线一样的,它的数据只有前和后两个方向。除了数组,队列、栈、链接也是线性表数据结构。
  • 连续的内存空间。就是说数据中的元素在内存中是连续存储的,正是因为这个特性,所以数据可以实现随机访问,也就是访问数据中的每个元素花的时间就是一样的,时间复杂度都是 O(1),查询数据特别快。

2. 它是一个原生方法,内部 C++ 编码实现,我们从 js 代码层面无法判断数据内部的存储结构,也就无法模拟实现。

小结

判断是否是数组的方法 优点 缺点 推荐度
Array.isArray() 标准、跨环境、最可靠 兼容性问题,只支持IE9+ ⭐⭐⭐⭐⭐
Object.prototype.toString.call() 最兼容、可靠 代码较长,并且可通过 Symbol.toStringTag 修改判断结果 ⭐⭐⭐⭐
instanceof 简单直观 通过 Object.setPrototypeOf 修改原型后判断不准确,跨 iframe 失效 ⭐⭐⭐
constructor 简单 constructor 可被修改 ⭐⭐
JSON.stringify 兼容性好 无法处理循环引用、性能差

在平时实际前端项目开发中,如果需要判断是否是数组,直接用 Array.isArray() 就好了,它内部通过 C++ 编码实现,判断其存储结构是否为数组,是最可靠的判断方法,如果需要封装一个通用的数据类型判断方法,可以采用 Object.prototype.toString.call()

❌
❌