ecmascript对象类型检测应统一使用object.prototype.tostring.call(),它跨版本兼容且精准识别内置类型(如map、symbol、bigint),辅以array.isarray()、typeof函数判断及symbol.iterator等接口检查,避开null、跨iframe原型失效等陷阱。

检测 ECMAScript 对象类型,关键不在于“不同版本”本身,而在于标准演进带来的新类型和检测手段变化。ECMAScript 规范本身不提供“按版本检测对象类型”的 API;实际开发中,我们用统一、可靠的方法识别值的类型,同时注意各版本新增类型(如 Symbol、BigInt、Promise、Map、Set 等)在检测时的兼容性与行为差异。
用 Object.prototype.toString.call() 精准识别内置对象类型
这是最稳定、跨版本兼容的通用方法,能区分几乎所有内置引用类型,不受 constructor 被篡改或原型链被污染的影响。
- 它返回形如
"[object Array]"、"[object Date]"、"[object RegExp]"的字符串 - ES6+ 新增类型也支持:
Object.prototype.toString.call(new Map())→"[object Map]" - ES2020 的
BigInt:返回"[object BigInt]";Symbol返回"[object Symbol]" - 自定义类可通过设置
[Symbol.toStringTag]控制输出,例如:class MyType { get [Symbol.toStringTag]() { return 'MyType'; } }
区分函数与普通对象:用 typeof + instanceof Function
typeof 是唯一能原生区分 function 和其他 object 的操作符,但要注意历史限制:
-
typeof fn === 'function'在所有现代环境(包括 ES5–ES2023)中可靠,适用于普通函数、箭头函数、async 函数 -
fn instanceof Function也可用,但依赖原型链完整性;若Function.prototype被修改,可能失效 - 注意:某些宿主对象(如某些浏览器中的
document.all)可能被误报为function,属边缘情况
检测 ES6+ 新增集合类型:优先用 toString,辅以构造器检查
像 Map、Set、WeakMap、WeakSet、Promise 等,不能靠 typeof(都返回 "object"),也不建议只依赖 instanceof(跨 iframe 或模块边界时原型不一致):
- 推荐组合:
Object.prototype.toString.call(val) === '[object Map]' - 若需判断是否具备某接口(如迭代能力),可用
val[Symbol.iterator]是否为函数 - 对
Promise,更稳妥的是检查typeof val.then === 'function' && typeof val.catch === 'function',而非仅靠toString(部分 polyfill 可能未实现)
避开常见陷阱:null、数组、日期等特殊值的处理
这些不是“版本差异”,而是规范长期存在的细节,必须显式处理:
-
null:typeof null === 'object'(历史原因),必须单独判断:val === null -
Array:Array.isArray(val)是 ES5 标准方法,比instanceof Array更安全(尤其跨 frame) -
Date、RegExp:toString最稳;val instanceof Date在同域下可用,但非绝对 -
NaN、Infinity属于Number类型,typeof正确返回"number",但需用isNaN()或Number.isNaN()判断是否为 NaN











