object.prototype.tostring 是最可靠的类型判断方式,通过 call 借用原生方法返回统一格式的 “[object xxx]”,再截取类型名,可精准区分所有内置类型,且兼容 null、undefined 及各类引用与原始类型。

在 JavaScript 中,Object.prototype.toString 是最可靠、最标准的类型判断方式,它能准确区分所有内置类型(包括 null、undefined、各种引用类型和原始类型),远比 typeof 和构造函数判断更健壮。
为什么 toString 能完美判断类型
Object.prototype.toString 内部通过读取对象的 [[Class]] 内部属性(ES5)或 Symbol.toStringTag(ES6+)生成字符串标识。对所有内置对象,它返回格式统一的 [object Xxx],且不可轻易被伪造(除非显式修改 Symbol.toStringTag)。
而 typeof null 返回 "object"、typeof [] 也是 "object"、typeof new Date() 还是 "object",完全无法区分;直接调用 {}.toString() 又可能被原型链污染或重写——所以必须用 Object.prototype.toString.call(value) 来“借用”未被篡改的原生方法。
标准用法:统一调用 + 字符串解析
核心写法固定:
- 用
Object.prototype.toString.call(value)获取精确类型字符串 - 截取中括号内名称(如
"[object Array]" → "Array") - 可封装为通用函数,避免重复写法
示例:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
typeOf(42); // "Number"
typeOf("hello"); // "String"
typeOf(true); // "Boolean"
typeOf(null); // "Null"
typeOf(undefined); // "Undefined"
typeOf([]); // "Array"
typeOf({}); // "Object"
typeOf(/a/g); // "RegExp"
typeOf(new Date()); // "Date"
typeOf(new Set()); // "Set"
typeOf(new Map()); // "Map"
typeOf(Symbol()); // "Symbol"
typeOf(BigInt(1)); // "BigInt"
typeOf(function(){}); // "Function"
注意边界情况和兼容性细节
虽然绝大多数场景都适用,但有几点需留意:
-
null和undefined在 ES5 中返回"Null"和"Undefined",各浏览器均支持,无需 polyfill - 自定义对象默认返回
"Object",除非显式设置Symbol.toStringTag - 某些宿主对象(如 IE 中的
document.all)可能返回非标准字符串,但现代环境基本无此问题 - Node.js 和浏览器环境行为一致,无需额外适配
进阶:封装成类型断言工具
实际项目中常需要布尔型判断,可基于 typeOf 扩展:
const is = {
Array: (v) => typeOf(v) === 'Array',
Object: (v) => typeOf(v) === 'Object',
Promise: (v) => typeOf(v) === 'Promise',
PlainObject: (v) => typeOf(v) === 'Object' && v.constructor === Object,
// 等等...
};
is.Array([1, 2]); // true
is.Object({}); // true
is.Object(new Date()); // false(它是 Date,不是 PlainObject)
这样既保持语义清晰,又避免每次重复写 call 和字符串处理。
不复杂但容易忽略:永远用 Object.prototype.toString.call,而不是 value.toString() 或 {}.toString.call —— 前者可能被重写,后者依赖空对象的原型链,不如直接绑定原生方法稳妥。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











