Object.prototype.toString.call()是最可靠的JavaScript类型判断方法,它能准确识别null、数组、Date、RegExp等所有类型且不受跨iframe影响;typeof仅对函数准确,instanceof在跨环境时失效。

typeof 和 instanceof 都不能可靠判断所有 JavaScript 数据类型,尤其对 null、数组、内置对象(如 Date、RegExp)和跨 iframe 构造的实例会出错。
typeof 对 null 和对象类型的误判
typeof null 返回 "object",这是历史遗留 bug;所有引用类型(除函数外)也都返回 "object",无法区分 Array、Date、RegExp 等。
-
typeof null→"object"(错误) -
typeof []→"object"(无法识别是数组) -
typeof new Date()→"object"(同上) -
typeof function() {}→"function"(唯一准确的函数判断)
instanceof 在跨 iframe 或不同全局环境下的失效
instanceof 依赖构造函数的原型链比对,而不同 iframe 或 Worker 中的 Array、Promise 等构造函数是不同引用,导致判断失败。
-
[].constructor === window.parent.Array→false(即使值是数组) -
iframe.contentWindow.Array === Array→false -
[1,2,3] instanceof iframe.contentWindow.Array→false(本该为true) - 对原始类型(如
42、"str")永远返回false
更可靠的替代方案:Object.prototype.toString.call()
该方法能稳定返回内部 [[Class]] 标签,且不受全局环境影响,是目前最通用的类型检测基础。
立即学习“Java免费学习笔记(深入)”;
Object.prototype.toString.call(42) // "[object Number]" Object.prototype.toString.call([]) // "[object Array]" Object.prototype.toString.call(null) // "[object Null]" Object.prototype.toString.call(undefined) // "[object Undefined]" Object.prototype.toString.call(/abc/) // "[object RegExp]" Object.prototype.toString.call(new Date())// "[object Date]" Object.prototype.toString.call(self) // "[object Window]"(在 iframe 中仍正确)
可封装为工具函数:
function typeOf(obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
typeOf([1,2]) // "array"
typeOf(null) // "null"
typeOf(new Set()) // "set"
实际项目中怎么选?
没有银弹。需按场景组合使用:
- 快速判断是否为函数 → 用
typeof fn === "function"(最安全) - 确认是否为数组 → 优先
Array.isArray()(ES5+,不跨环境时最快) - 需要精确识别内置对象或处理跨环境 → 必须用
Object.prototype.toString.call() - 检查自定义类实例 →
instanceof可用,但要确保构造函数来自同一全局上下文 - 判断原始类型(string/number/boolean)→
typeof足够,但记得null单独处理
多数现代库(如 Lodash 的 _.isXxx)底层都基于 toString.call 实现,因为它是唯一不被环境隔离影响的通用机制。











