typeof能准确判断string、number、boolean、undefined、function、symbol和bigint,但对所有对象(含数组、日期、正则、null等)均返回"object",无法区分具体引用类型。
typeof 是最常用的类型检测操作符,但它对引用类型的支持很有限。它能准确区分 string、number、boolean、undefined、function 和 symbol,但对所有对象(包括数组、正则、日期、null)都返回 "object"。
特别注意:typeof null === "object" 是历史遗留 bug,至今未修复。
typeof [] → "object"
typeof null → "object"
typeof new Date() → "object"
typeof /abc/ → "object"
typeof Promise.resolve() → "object"
每个内置类型的构造函数都有对应的内部 [[Class]] 标签,Object.prototype.toString.call() 可以读取这个标签,返回形如 "[object Array]" 的字符串。这是目前最通用、最标准的类型检测方法。
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(BigInt(1)) // "[object BigInt]" Object.prototype.toString.call(1n) // "[object BigInt]"
实际使用时建议封装成工具函数:
立即学习“Java免费学习笔记(深入)”;
function typeOf(val) {
return Object.prototype.toString.call(val).slice(8, -1).toLowerCase();
}
typeOf([1, 2]) // "array"
typeOf(null) // "null"
typeOf(new Set())// "set"
Array.isArray() 是检测数组的首选,比 toString 更语义化、性能略优,且在跨 iframe 场景下仍可靠(instanceof Array 在跨环境时会失效)。
instanceof 适用于你明确知道构造函数来源、且不涉及多全局环境(比如多个 iframe 或 Web Worker)的场景。它依赖原型链,对原始值无效,也不能识别基础类型。
Array.isArray([]) → true(推荐)[] instanceof Array → true(同源下可用){} instanceof Object → true,但 new String('a') instanceof Object 也返回 true,容易误判包装对象"" instanceof String → false(原始字符串不是实例)ES2025 引入了 BigInt,ES2025 加入了 Temporal(暂未广泛支持),还有 Promise、Map、WeakRef 等。它们都不能靠 typeof 准确识别,必须依赖 toString 或专用 API。
typeof 1n → "bigint"(这是少数 typeof 能正确识别的新类型)typeof Promise.resolve() → "object",但 toString 返回 "[object Promise]"
Promise.resolve() instanceof Promise → true(仅限当前 realm)typeof window(浏览器中)→ "object",但 toString 返回 "[object Window]",不是标准类型检测自定义类实例时,instanceof 最直接;检测内置对象类型时,toString 最稳;判断是否为原始值,可先用 typeof 快速分流,再针对性处理引用类型。