前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库Array.isArray 与 instanceof 跨 realm 区别
JavaScript数组与集合

Array.isArray 和 instanceof Array 有什么区别?为什么跨 iframe 就失效了?

instanceof Array 沿着原型链找当前环境的 Array.prototype,找到就是 true。每个 iframe 都有自己的一套 Array,那边创建的数组,原型链上是它自己的 Array.prototype,所以在父页面里 instanceof 是 false。而 Array.isArray 不看原型,直接检查对象是不是真正的数组,跨 iframe 也能判断对。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#数组与集合
先看核心答案读代码示例
理解线索

两种判断各看什么

  1. instanceof Array原型链上有没有当前环境的 Array.prototype,原型能被随意修改
  2. Array.isArray对象是不是用数组方式创建的,和原型无关,改不掉
  3. realm一套独立的全局环境,iframe、Worker、Node.js 的 vm 上下文各有一套内置对象

Array.isArray 只认普通数组,Uint8Array 这类 TypedArray 虽然有下标和 length,结果也是 false。

核心回答

先记住这个答案

instanceof Array 检查的是原型链:沿着对象的 __proto__ 往上找,看有没有碰到当前环境里的 Array.prototype。而 Array.isArray 检查的是对象本身是不是真正的数组,和原型无关。每个 iframe 都有自己独立的全局环境,也就有自己的 Array 构造函数和 Array.prototype,iframe 里创建的数组,原型链上是 iframe 的 Array.prototype,父页面的 instanceof Array 自然找不到,返回 false,而 Array.isArray 仍然返回 true。反过来,一个普通对象只要把原型设成 Array.prototype,就能骗过 instanceof,但骗不过 Array.isArray。

  • instanceof 看原型链,Array.isArray 看对象本身
  • 每个 iframe 有独立的 Array,所以 instanceof 跨过去就失效
  • 原型是数组原型的普通对象,instanceof 为 true 但不是数组
  • 判断数组一律用 Array.isArray

原型能改,数组身份改不掉

先不用 iframe,在同一个环境里就能看出两者的差别。

伪造原型、删掉原型和 TypedArrayJavaScript
const fake = Object.create(Array.prototype) // 原型是数组原型,但不是数组
console.log(fake instanceof Array, Array.isArray(fake))

const real = [1, 2]
Object.setPrototypeOf(real, null) // 真数组,原型被改掉了
console.log(real instanceof Array, Array.isArray(real))

console.log(Array.isArray(new Uint8Array(2)), Array.isArray(Array.prototype))
查看输出与解释
true false
false true
false true

fake 能调用 push、map,看起来像数组,但它是普通对象创建的,给它设置下标时 length 不会自动更新,Array.isArray 就认出来了。real 被改掉了原型,连 map 都调不了了,但它的「出身」还是数组,Array.isArray 照样返回 true。 可以把 instanceof 想成看对方的工牌,工牌可以借、可以换;Array.isArray 是查身份证,出生时就定了。规范里的说法是,数组是一种特殊的对象(exotic object),它的 length 会随下标自动变化,Array.isArray 检查的就是这个内部特征。 最后一行有两个冷知识:TypedArray 不算数组;Array.prototype 本身却是一个真数组,所以 Array.isArray(Array.prototype) 是 true。

跨 iframe 为什么会失效

realm 可以理解成一套独立的 JavaScript 全局环境,里面有自己的 Object、Array、Function 等内置对象。每个 iframe、每个 Worker、Node.js 里每个 vm 上下文都是一个 realm。

父页面判断 iframe 里的数组JavaScript
const iframe = document.createElement('iframe')
document.body.appendChild(iframe)
const IframeArray = iframe.contentWindow.Array

const arr = new IframeArray(1, 2, 3) // 在 iframe 的环境里创建
console.log(IframeArray === Array) // false,两个不同的构造函数
console.log(arr instanceof Array) // false,原型链上是 iframe 的 Array.prototype
console.log(Array.isArray(arr)) // true

两个页面的 Array 是两个不同的函数,各自的 prototype 也是两个不同的对象。arr 的原型链上只有 iframe 那一份,父页面拿自己的 Array.prototype 去找当然找不到。实际项目里,微前端、富文本编辑器、老的 iframe 嵌套页面,都会遇到从另一个 realm 传过来的数组。postMessage 传过来的数据不会有这个问题,因为它会用结构化克隆在当前环境里重新创建一份。

回答前,多想一步

容易答错的地方

以为 Object.prototype.toString 判断万无一失
Object.prototype.toString.call(x) === '[object Array]' 是 ES5 之前的跨 realm 方案,但它能被 Symbol.toStringTag 伪造。给普通对象设置 [Symbol.toStringTag]: 'Array',返回的也是 [object Array]。现在直接用 Array.isArray。
以为 instanceof 只在 iframe 里才会出错
只要原型被改过,同一个页面里也会出错。上面的 fake 和 real 就是例子。instanceof 本质上只回答「原型链上有没有某个对象」,它不回答「这是不是某种类型」。
以为类数组、TypedArray 也会返回 true
arguments、NodeList、Uint8Array 都有 length 和下标,但 Array.isArray 全部返回 false。需要统一处理时,先用 Array.from 转成真数组。
试着用自己的话回答

面试官还会怎么问?

Array.isArray 对 Proxy 包装的数组返回什么?

返回 true,因为 Array.isArray(new Proxy([], {})) 会穿过 Proxy 去检查它包装的目标对象。Vue 3 的响应式数组就是用 Proxy 包装的,所以 Array.isArray(reactive([])) 是 true。

其它内置类型跨 realm 怎么判断?

没有通用方案。Array 有 Array.isArray;Promise 可以判断是不是 thenable;Date、RegExp 这类常用 Object.prototype.toString 的返回值判断,接受它可以被伪造的前提。能避免跨 realm 传对象,就尽量在边界上转换成当前环境的对象。

继承 Array 的子类实例用两者判断结果是什么?

定义 class MyList extends Array {} 之后,new MyList() 用 instanceof Array 和 Array.isArray 都是 true。子类的构造过程最终由 Array 创建对象,所以它是真数组,原型链上也有 Array.prototype。

从一道题,走向一组知识

把知识连起来

数组与集合

数字数组直接 sort 为什么会把 10 排在 9 前面?

确认是数组之后,排序时还要注意默认 sort 按字符串比较,数字要传比较函数。

数组与集合

Array.from 能转换类数组,为什么数组展开有时却会报错?

如果只是想逐个处理元素,不必非要是真数组,Array.from 能把可迭代对象和类数组统一转换。

数组与集合

怎么手写 Symbol.iterator,让普通对象支持 for...of 和展开?

普通对象加上 Symbol.iterator 就能被 for...of 遍历,但 Array.isArray 依然是 false。

参考资料

  • MDN:Array.isArray
  • MDN:instanceof

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 原型能改,数组身份改不掉
  3. 跨 iframe 为什么会失效
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑