Array.isArray()是唯一能跨执行上下文(如iframe、Worker)可靠判断数组的方法,因其直接读取引擎内部类型标记,不依赖原型链或构造函数引用,而instanceof和constructor在跨上下文时因构造函数隔离必然失效。

跨执行上下文(Context)做类型判断,核心难点在于不同上下文中的构造函数彼此隔离——比如 iframe 里的 [] 和主页面的 Array 是两个完全不同的函数,instanceof 和 constructor === Array 都会失效。真正可靠的做法只有一个:用原生的 Array.isArray()。
为什么 instanceof 和 constructor 不行
这些方法依赖原型链或构造函数引用,而跨上下文时:
- iframe、Worker、Node.js 的
vm.Context中的Array是独立对象,内存地址不同 -
arr.constructor === window.Array返回false,哪怕它确实是数组 -
arr instanceof window.Array同样返回false,因为原型链查不到主环境的Array.prototype
Array.isArray() 为什么能跨上下文工作
它不看构造函数,也不走原型链,而是直接读取 JavaScript 引擎内部的类型标记(如 [[Class]] 或更现代的隐藏属性)。只要该值符合规范定义的 Array 实例,就返回 true:
- 支持 iframe、
new Worker()、eval创建的上下文 - 对稀疏数组、冻结数组、带自定义属性的数组同样准确
- ES5 就已标准化,所有现代环境都兼容
其他类型怎么判断才安全
没有统一的 isXxx() 方法时,需结合场景选择策略:
-
Date:用
Object.prototype.toString.call(val) === '[object Date]' -
RegExp:同上,
'[object RegExp]' -
Promise:检查
typeof val.then === 'function'(注意需配合val !== null && typeof val === 'object') -
自定义类实例:若必须跨上下文识别,建议通过序列化/反序列化传递类型标识,或约定使用
Symbol.toStringTag并配合toString()检测
实际开发中的建议
处理外部输入、插件通信、跨 frame 数据交换时:
- 一律优先用
Array.isArray()判断数组,别手写val && typeof val === 'object' && val.length !== undefined这类脆弱逻辑 - 避免在类型判断中混用
instanceof和全局构造器,尤其当数据可能来自postMessage或SharedArrayBuffer - 如果用 TypeScript,编译后的 JS 仍需面对运行时跨上下文问题,类型断言不能替代运行时检测

















