Object.prototype.toString.call() 是判断 JavaScript 数据类型最可靠的方式,因其不依赖可篡改的原型链或 constructor,而是基于内部属性识别类型,能准确区分 null、undefined 及 ES6+ 新类型。

直接用 Object.prototype.toString.call() 是判断 JavaScript 数据类型的最可靠方式,它能绕过原型链污染、构造函数被改写等陷阱,返回标准的 [object Type] 字符串。
为什么 call 比 instanceof 和 constructor 更稳
instanceof 依赖原型链,跨 iframe 或继承链断裂时会失效;constructor 属性可被随意修改,完全不可信。而 Object.prototype.toString 是原生方法,内部通过对象的内部属性 [[Class]](ES5)或 [[TypedArray]] 等机制识别类型,不依赖用户可篡改的属性。
- 数组:
Object.prototype.toString.call([])→"[object Array]" - 正则:
Object.prototype.toString.call(/a/)→"[object RegExp]" - Promise:
Object.prototype.toString.call(Promise.resolve())→"[object Promise]" - null 和 undefined 也能准确区分:
call(null)→"[object Null]",call(undefined)→"[object Undefined]"
封装一个通用 typeOf 函数
提取字符串中的类型名,去掉 [object 和 ],统一转为小写,便于比较:
function typeOf(obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
这样调用更直观:
-
typeOf([])→"array" -
typeOf(new Date())→"date" -
typeOf(new Map())→"map" -
typeOf(123)→"number"
增强版:支持多类型校验与断言
可扩展成接受多个类型名,支持「或」逻辑,并附带类型断言能力:
function isType(obj, ...types) {
const actual = typeOf(obj);
return types.some(t => t.toLowerCase() === actual);
}
// 使用示例
isType([], 'array', 'object') // true
isType(42, 'string', 'number') // true
isType(null, 'null') // true
搭配 TypeScript 类型守卫或运行时校验非常实用,尤其在处理 API 返回值、表单输入等不确定数据时。
注意边界情况与兼容性
该方法在所有现代浏览器和 Node.js 中都稳定支持,包括 IE6+。唯一要注意的是:
- 自定义类实例默认返回
"object",除非显式定义Symbol.toStringTag - 某些宿主对象(如 IE 的 ActiveX)可能返回非标准字符串,但这类场景已基本消失
- ES6+ 新增的类型(如
BigInt、WeakMap)均被正确识别:typeOf(1n)→"bigint"

















