JS精准判断一个对象是不是数组的方法

 更新时间:2026年05月12日 08:29:32   作者:yqcoder  
这篇文章主要介绍了JavaScript中判断数组的方法,包括Array.isArray()、instanceof、Object.prototype.toString三种方法的优缺点,并给出了一些使用技巧和避坑指南,其中array.isArray()是最推荐使用的方法,准确可靠,跨上下文安全,是最安全、易读的选择

为什么判断数组这么难?

在 JavaScript 中,数组本质上也是一种对象

console.log(typeof []); // "object"
console.log(typeof {}); // "object"

因为 typeof 只能区分基本类型(string, number, boolean, undefined, symbol, bigint)和引用类型(统一返回 object,函数返回 function),所以它无法直接告诉我们:“嘿,这是个数组!”

我们需要更高级的手段来揭开它的真面目。

1. 王者方案:Array.isArray()

这是 ES5 引入的标准方法,也是现代开发中的首选

console.log(Array.isArray([])); // true
console.log(Array.isArray({})); // false
console.log(Array.isArray("hello")); // false
console.log(Array.isArray(null)); // false

优点

  • 语义清晰:代码可读性极高,一眼就能看懂意图。
  • 准确可靠:内部实现机制完善,能正确处理各种边界情况。
  • 跨上下文安全:即使数组来自不同的 iframe 或 window,它依然能正确识别(因为它不依赖原型链继承关系,而是检查内部标签)。

缺点

  • 兼容性:不支持 IE8 及以下版本(但在 2024 年,这几乎不再是问题)。

博主建议
无脑选它! 除非你有极其特殊的兼容需求,否则 Array.isArray 就是你的唯一选择。

2. 经典方案:instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

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

const obj = {};
console.log(obj instanceof Array); // false

优点

  • 直观:符合面向对象编程的思维逻辑,“这个实例是不是由 Array 构造函数创建的?”

缺点

跨上下文失效:这是最大的坑!
如果页面中有多个 iframe,每个 iframe 都有自己独立的执行环境(也就是独立的 Array 构造函数)。

// 假设 iframe 中的数组传到了主窗口
iframeArray instanceof Array; // false!
// 因为 iframeArray 的原型链指向的是 iframe 里的 Array.prototype,
// 而主窗口里的 Array 是另一个构造函数。
  • 可被篡改:如果开发者手动修改了原型链,instanceof 可能会给出错误结果。

3. 通用方案:Object.prototype.toString

这是一种“黑科技”写法,利用对象内部的 [[Class]] 属性(在 ES5 之前称为 Class 内部属性,现在通过 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]"

优点

  • 万能 钥匙:不仅能判断数组,还能精准判断 Date, RegExp, Function, Null, Undefined 等所有内置类型。
  • 跨上下文安全:和 Array.isArray 一样,它不受不同 window/iframe 的影响,因为它读取的是底层引擎标记。

缺点

  • 写法繁琐Object.prototype.toString.call(obj) 太长,容易写错。
  • 可读性差:新手可能看不懂这是在干嘛。

技巧
你可以封装一个工具函数:

const typeCheck = (obj) => Object.prototype.toString.call(obj).slice(8, -1);
console.log(typeCheck([])); // "Array"

4. 避坑指南:typeof与constructor

陷阱 1:typeof

如前所述,typeof [] 返回 "object",完全无法区分数组和普通对象。千万别用!

陷阱 2:constructor

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

看起来不错?但它有两个致命弱点:

可被修改arr.constructor 是可以被人为赋值的,不可信。

arr.constructor = String;
console.log(arr.constructor === Array); // false (误判!)

null/undefined 报错nullundefined 没有构造函数,访问会报错。

5. 跨框架/跨窗口场景的特殊陷阱

这是高级前端面试的常客。

场景:你的主页面嵌入了一个 iframe,iframe 里有一个数组 iframeArr,你把它传回主页面。

方法结果原因
iframeArr instanceof ArrayFalse主页面的 Array 和 iframe 的 Array 不是同一个引用。
Array.isArray(iframeArr)True规范规定它检查内部插槽,不依赖原型链。
Object.prototype.toString.call(iframeArr)“[object Array]”同样基于内部标签,不受上下文影响。

结论
在涉及多窗口、Web Worker 或微前端架构时,严禁使用 instanceof 判断数组,必须使用 Array.isArraytoString 方法。

6.  总结与最佳实践

方法准确性跨上下文安全可读性推荐指数
Array.isArray()⭐⭐⭐⭐⭐✅ 是⭐⭐⭐⭐⭐🌟🌟🌟🌟🌟
Object.prototype.toString⭐⭐⭐⭐⭐✅ 是⭐⭐🌟🌟🌟
instanceof⭐⭐⭐❌ 否⭐⭐⭐⭐🌟🌟
constructor⭐⭐❌ 否⭐⭐⭐❌ 不推荐
typeof❌ 无效-⭐⭐⭐⭐⭐❌ 禁止使用

博主寄语
判断数组看似简单,实则暗藏玄机。

记住一条铁律
永远优先使用 Array.isArray()
它不仅是最标准的 API,也是最安全、最易读的选择。
只有在需要同时判断多种类型(如写一个通用的 typeOf 工具库)时,才考虑使用 Object.prototype.toString

以上就是JS精准判断一个对象是不是数组的方法的详细内容,更多关于JS判断对象是不是数组的资料请关注脚本之家其它相关文章!

相关文章

  • 深入理解webpack process.env.NODE_ENV配置

    深入理解webpack process.env.NODE_ENV配置

    这篇文章主要介绍了深入理解webpack process.env.NODE_ENV配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • iScroll中事件点击触发两次解决方案

    iScroll中事件点击触发两次解决方案

    iScroll是我们在做手机网页中常用的滑动控件之一。单说其功能已相当丰富。但个别时候也是会掉坑的,正好这次就遇上了。在android的app中嵌入网页时不少手机会出现一次点击两次触发的现象。经过一段时间的折腾,总算想到了一个还算合理的解决放案。
    2015-03-03
  • uniapp中实现canvas超出屏幕滚动查看功能

    uniapp中实现canvas超出屏幕滚动查看功能

    亲爱的小伙伴,当你需要在uniapp中使用canvas绘制一个超长图,就类似于横向的流程图时,这个canvas超出屏幕部分拖动屏幕查看会变得十分棘手,怎么解决这个问题呢,下面小编给大家介绍uniapp中实现canvas超出屏幕滚动查看功能,感兴趣的朋友一起看看吧
    2024-03-03
  • JavaScript实现AOP详解(面向切面编程,装饰者模式)

    JavaScript实现AOP详解(面向切面编程,装饰者模式)

    下面小编就为大家分享一篇JavaScript实现AOP的方法(面向切面编程,装饰者模式),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 简单谈谈JavaScript的同步与异步

    简单谈谈JavaScript的同步与异步

    这篇文章主要介绍了简单谈谈JavaScript的同步与异步的相关资料,需要的朋友可以参考下
    2015-12-12
  • 记录微信小程序 height: calc(xx - xx);无效问题

    记录微信小程序 height: calc(xx - xx);无效问题

    这篇文章主要介绍了微信小程序 - height: calc(xx - xx);无效 问题,文中给大家扩展介绍下jquery点击添加样式,再次点击移除样式的实例代码,需要的朋友可以参考下
    2019-12-12
  • JS 中在严格模式下 this 的指向问题

    JS 中在严格模式下 this 的指向问题

    这篇文章主要介绍了JS 中在严格模式下this的指向问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 基于insertBefore制作简单的循环插空效果

    基于insertBefore制作简单的循环插空效果

    这是一个基于insertBefore制作简单的循环插空效果,实现的数字下面循环插空效果,给需要的朋友分享。
    2015-09-09
  • JavaScript编写css自定义属性的示例代码

    JavaScript编写css自定义属性的示例代码

    自定义属性(有时候也被称作CSS变量或者级联变量)是由CSS作者定义的,它包含的值可以在整个文档中重复使用,由自定义属性标记设定值,,由var() 函数来获取值,本文就给大家介绍了JavaScript编写css自定义属性,需要的朋友可以参考下
    2024-12-12
  • JavaScript的高级概念和用法详解

    JavaScript的高级概念和用法详解

    JavaScript语言不断发布一些新特性,感觉要上天的节奏啊。本文搜集整理了一些它的高级概念和用法,需要的朋友可以参考下
    2022-07-07

最新评论