最稳妥的类型判断策略是先用 typeof 区分基本类型,再用 object.prototype.tostring.call() 识别复杂类型;前者快速筛选字符串、数字、布尔、函数、undefined,后者精准区分数组、null、date、regexp 等对象类型。

直接用 typeof 判断基本类型,再用 Object.prototype.toString.call() 区分复杂类型,是最稳妥、最常用的混合策略。
先用 typeof 快速筛出基本类型
它响应快、写法简单,适合快速排除字符串、数字、布尔、函数、undefined 这些明确类型:
-
typeof value === "string"→ 确认是原始字符串 -
typeof value === "number"→ 包括NaN和Infinity,但注意NaN不等于自身 -
typeof value === "function"→ 准确识别函数(包括箭头函数、class 声明) -
typeof value === "undefined"→ 安全检测未声明或未赋值变量 -
typeof value === "boolean"→ 只匹配true/false原始值
对 typeof 返回 "object" 的值,再用 toString.call 深度识别
因为 typeof null、typeof []、typeof {}、typeof new Date() 全是 "object",必须靠 Object.prototype.toString.call() 拆解:
Object.prototype.toString.call([]) === "[object Array]"Object.prototype.toString.call(null) === "[object Null]"Object.prototype.toString.call(undefined) === "[object Undefined]"Object.prototype.toString.call(new Date()) === "[object Date]"Object.prototype.toString.call(/abc/) === "[object RegExp]"Object.prototype.toString.call(new Map()) === "[object Map]"
建议统一转小写再比对,避免大小写敏感问题:
Object.prototype.toString.call(value).toLowerCase().includes("array")
避开常见陷阱
几个容易出错的地方要特别留心:
- 别直接调用
value.toString()—— 数组、日期、正则都重写了该方法,返回的是格式化字符串,不是类型标识 - 不要省略
.call();写成Object.prototype.toString(value)会失效,必须绑定上下文 -
instanceof不能用于跨 iframe 或不同全局环境的对象,而toString.call不受此限制 - 自定义类实例默认返回
[object Object],如需区分,得靠constructor.name或 Symbol.toStringTag
封装一个通用类型判断工具
实际项目中可封装成简洁函数,兼顾可读与健壮性:
function typeOf(value) {
const type = typeof value;
if (type !== "object") return type;
return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}
// 使用示例:
typeOf([]); // "array"
typeOf(null); // "null"
typeOf(42); // "number"
typeOf(new Set()); // "set"











