JavaScript中判断两个值类型是否相同需用Object.prototype.toString.call()获取标准类型标签再比对,因其能准确区分所有内置类型且不受跨环境影响;其他方法如constructor、instanceof存在篡改或跨上下文失效风险。

JavaScript 中不能直接用 === 或 == 判断两个对象的“数据类型是否相同”,因为对象比较的是引用地址,不是结构或构造来源。要精确判断两个值的数据类型是否一致,关键在于分别识别各自的真实类型,再做字符串比对。
用 Object.prototype.toString.call() 获取标准类型标签
这是最可靠的方式,能准确区分 Array、Date、RegExp、Map、Set、Null、Undefined 等所有内置类型,不受跨 iframe 或原型篡改影响。
-
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]"
封装一个类型提取函数:
function getType(val) {
return Object.prototype.toString.call(val).slice(8, -1);
}
// getType([]) → "Array"
// getType({}) → "Object"
// getType(new Date()) → "Date"
判断两个值类型是否完全相同:
立即学习“Java免费学习笔记(深入)”;
function sameType(a, b) {
return getType(a) === getType(b);
}
sameType([], new Set()); // false
sameType([], [1, 2]) // true
sameType(null, undefined) // false("Null" ≠ "Undefined")
对数组等高频类型优先使用专用方法
部分类型有更语义明确、性能略优的原生方法,适合在已知待测范围时使用:
- 数组:
Array.isArray(a) && Array.isArray(b) - 函数:
typeof a === 'function' && typeof b === 'function' - 正则:
a instanceof RegExp && b instanceof RegExp(注意跨环境失效风险) - Promise:
a instanceof Promise && b instanceof Promise
但这些方法无法覆盖全部类型(比如无法区分 Date 和 Number),所以仅作补充,不替代 toString.call()。
避免 constructor 和 instanceof 的陷阱
这两个方式看似直观,但实际容易出错:
-
constructor属性可被显式修改或丢失(如Object.create(null)) -
instanceof在多 iframe 或不同执行上下文(如 Web Worker)中会失效,因为不同环境的Array构造函数不是同一个引用 -
null和undefined没有constructor,访问会报错
例如:
const arr = [];
arr.constructor = String; // 手动篡改
arr.constructor === Array; // false ❌
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);
const OtherArray = iframe.contentWindow.Array;
[1,2] instanceof OtherArray; // false —— 即使是数组也不成立 ❌
处理自定义类和 Symbol.toStringTag
对于自定义类,若希望 toString.call() 返回预期类型,需设置 Symbol.toStringTag:
class MyClass {}
MyClass.prototype[Symbol.toStringTag] = 'MyClass';
Object.prototype.toString.call(new MyClass()); // "[object MyClass]"
这样就能让自定义类型也纳入统一判断体系。未设置时,默认返回 "[object Object]",与普通对象无法区分。
本质上,精确判断两个对象的类型是否一致,就是分别获取它们的内部 [[Class]] 标签并比对——Object.prototype.toString.call() 是目前唯一稳定、全面、符合规范的手段。


















