object.prototype.tostring.call()能准确判断类型,因其直接调用原始方法,不依赖被篡改的原型链;而修改array.prototype.tostring或object.prototype.tostring会覆盖默认行为,导致[].tostring()等返回非标准结果。

直接用 Object.prototype.toString.call() 判断数据类型,能绕过对象自身原型链上的 toString 方法,避免因原型被篡改导致类型识别错误。
为什么原型修改会影响 toString?
JavaScript 中很多对象(如数组、日期、正则等)都继承自 Object.prototype,默认调用 toString 会返回类似 [object Array] 的字符串。但如果有人给 Array.prototype.toString 或 Object.prototype.toString 赋了新函数,原生行为就被覆盖了——比如:
Array.prototype.toString = () => 'hacked';Object.prototype.toString = () => 'broken';
这时再写 [].toString() 或 ({}).toString() 就得不到标准结果,类型判断就失效了。
用 call 绑定原始方法最可靠
Object.prototype.toString 是一个通用方法,它内部通过 this 的内部属性(如 [[Class]] 或现代的 [[Symbol.toStringTag]])来识别类型。只要把任意值作为 this 传进去,就能得到标准标识:
-
Object.prototype.toString.call([])→"[object Array]" -
Object.prototype.toString.call(new Date())→"[object Date]" -
Object.prototype.toString.call(null)→"[object Null]" -
Object.prototype.toString.call(undefined)→"[object Undefined]"
因为是直接调用原始方法,不经过实例的原型链查找,所以无论原型怎么改,结果都不受影响。
封装成安全的类型判断工具
可以基于这个机制写一个健壮的 getType 工具函数:
function getType(value) {
const str = Object.prototype.toString.call(value);
return str.slice(8, -1); // 去掉 "[object " 和 "]"
}
// 使用示例
getType([]); // "Array"
getType(/abc/); // "RegExp"
getType(new Set()); // "Set"
getType(123); // "Number"
注意:不要用 instanceof 或 typeof 替代——typeof null 是 "object",typeof [] 也是 "object",而 instanceof 在跨 iframe 或重写构造函数时会失效。
实际项目中的常见误用提醒
有些开发者会简写为 {}.toString.call(x),这其实有风险——如果 Object.prototype.toString 被改写,{} 的原型上也会继承那个被改的版本。正确做法始终是显式引用原始方法:
- ✅ 安全:
Object.prototype.toString.call(x) - ❌ 不安全:
({}).toString.call(x)、Object.toString.call(x)(Object.toString是构造函数自己的方法,不是原型上的)
另外,ES6 后可配合 Symbol.toStringTag 自定义类型标签,但 Object.prototype.toString.call() 仍是最底层、最兼容的兜底方案。











