object.prototype.tostring.call() 是 js 类型判断最稳的方式,它直接读取对象底层类型标识,不依赖原型链或构造函数,可准确区分 null、数组、正则等,且跨 iframe 依然可靠。

JS 类型判断最稳的方式,就是 Object.prototype.toString.call()。它不看表面、不走原型链、不依赖构造函数,直接读取对象底层的类型标识,几乎无盲区。
为什么它比 typeof 更靠谱
typeof 对很多值都返回 "object":null、数组、正则、日期、Map……全被“一锅端”。它连 null 和普通对象都分不清,更别说 Array 和 Date 的区别了。
- null → "object"(历史 bug)
- [] → "object"
- /abc/ → "object"
- new Date() → "object"
而 Object.prototype.toString.call() 返回的是带类型名的标准字符串,比如:
-
Object.prototype.toString.call(null)→ "[object Null]" -
Object.prototype.toString.call([])→ "[object Array]" -
Object.prototype.toString.call(/a/g)→ "[object RegExp]" -
Object.prototype.toString.call(new Set())→ "[object Set]"
怎么用才顺手
每次都写一长串太麻烦,建议封装成一个简洁工具函数:
const typeOf = val => {
const raw = Object.prototype.toString.call(val);
return raw.slice(8, -1).toLowerCase();
};
使用起来就很直观:
-
typeOf([1, 2])→ "array" -
typeOf(new Promise(() => {}))→ "promise" -
typeOf(BigInt(123))→ "bigint" -
typeOf(undefined)→ "undefined"
注意 Symbol.toStringTag 的影响
ES6+ 允许对象自定义 Symbol.toStringTag,这会让 toString.call() 返回你设定的名称:
class MyType {
get [Symbol.toStringTag]() { return 'MyType'; }
}
Object.prototype.toString.call(new MyType()); // "[object MyType]"
这对扩展类型识别是好事,但也要留意——它可能掩盖真实构造器,比如自定义类没设这个属性时,默认还是 "[object Object]"。
跨 iframe 场景也稳
instanceof 在不同 window 环境下会失效(因为 Array 构造函数不是同一个),但 toString.call() 不依赖全局环境,只读内部属性,所以能安全用于跨 iframe、跨 sandbox 的类型检测。
比如在 iframe 里创建的数组,主页面也能准确识别为 "[object Array]"。











