在JavaScript开发过程中,我们经常需要判断两个对象的内容是否完全一致,但直接使用==或者===比较对象时,实际比较的是两个对象的引用地址,只有两个变量指向同一个对象时才会返回true,无法判断对象内部属性是否相同。那么JavaScript中如何判断两个对象是否相等呢?本文将详细介绍不同场景下的实现方案。

浅比较的实现方式
浅比较只判断对象的第一层属性是否相等,不递归比较嵌套对象的内部属性,适用于对象层级较浅、没有嵌套复杂结构的场景。
手动实现浅比较函数
浅比较的核心逻辑是先判断两个对象的键数量是否一致,再逐一比较每个键对应的值是否相等,实现代码如下:
function shallowEqual(obj1, obj2) {
// 先判断两个对象是否是同一个引用
if (obj1 === obj2) return true;
// 判断两个值是否都是对象且不为null
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return false;
}
// 获取两个对象的键数组
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
// 键数量不同直接返回false
if (keys1.length !== keys2.length) return false;
// 遍历比较每个键的值
for (let key of keys1) {
if (obj1[key] !== obj2[key]) {
return false;
}
}
return true;
}
// 测试示例
const a = { name: '张三', age: 20 };
const b = { name: '张三', age: 20 };
const c = { name: '李四', age: 20 };
console.log(shallowEqual(a, b)); // true
console.log(shallowEqual(a, c)); // false使用Object.keys结合every实现
也可以利用数组的every方法简化浅比较的逻辑,代码如下:
function shallowEqualSimplify(obj1, obj2) {
if (obj1 === obj2) return true;
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return false;
}
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
return keys1.every(key => obj1[key] === obj2[key]);
}深比较的实现方式
深比较会递归遍历对象的所有层级,判断所有嵌套的属性是否完全一致,适用于对象结构复杂、存在多层嵌套的场景。
基础深比较函数实现
深比较需要处理对象、数组、基本类型等不同情况,同时要规避循环引用的问题,基础实现代码如下:
function deepEqual(obj1, obj2, visited = new WeakMap()) {
// 基本类型直接比较
if (obj1 === obj2) return true;
// 判断是否为对象类型且不为null
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return false;
}
// 处理循环引用,避免递归死循环
if (visited.has(obj1) && visited.get(obj1) === obj2) return true;
visited.set(obj1, obj2);
// 处理数组情况
if (Array.isArray(obj1) && Array.isArray(obj2)) {
if (obj1.length !== obj2.length) return false;
for (let i = 0; i < obj1.length; i++) {
if (!deepEqual(obj1[i], obj2[i], visited)) return false;
}
return true;
}
// 处理普通对象情况
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (let key of keys1) {
if (!obj2.hasOwnProperty(key)) return false;
if (!deepEqual(obj1[key], obj2[key], visited)) return false;
}
return true;
}
// 测试示例
const objA = { name: '张三', info: { age: 20, hobby: ['篮球', '足球'] } };
const objB = { name: '张三', info: { age: 20, hobby: ['篮球', '足球'] } };
const objC = { name: '张三', info: { age: 20, hobby: ['篮球'] } };
console.log(deepEqual(objA, objB)); // true
console.log(deepEqual(objA, objC)); // false特殊场景处理
上述基础深比较函数没有处理Date、RegExp等特殊对象,如果需要支持这些类型,可以补充对应的判断逻辑:
function deepEqualEnhance(obj1, obj2, visited = new WeakMap()) {
if (obj1 === obj2) return true;
if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
return false;
}
// 处理Date对象
if (obj1 instanceof Date && obj2 instanceof Date) {
return obj1.getTime() === obj2.getTime();
}
// 处理RegExp对象
if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
return obj1.toString() === obj2.toString();
}
// 处理循环引用
if (visited.has(obj1) && visited.get(obj1) === obj2) return true;
visited.set(obj1, obj2);
// 处理数组
if (Array.isArray(obj1) && Array.isArray(obj2)) {
if (obj1.length !== obj2.length) return false;
for (let i = 0; i < obj1.length; i++) {
if (!deepEqualEnhance(obj1[i], obj2[i], visited)) return false;
}
return true;
}
// 处理普通对象
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (let key of keys1) {
if (!obj2.hasOwnProperty(key)) return false;
if (!deepEqualEnhance(obj1[key], obj2[key], visited)) return false;
}
return true;
}常见判断方式的局限性
很多开发者会使用JSON.stringify()将两个对象转为字符串后比较,这种方法存在明显的局限性:
- 无法处理函数、undefined、Symbol等类型,这些值在序列化时会被忽略或转为null
- 无法处理循环引用的对象,会直接抛出错误
- 对象的属性顺序不同但内容相同时,序列化后的字符串可能不同,导致判断错误
- Date对象会被序列化为字符串,不同Date实例如果时间相同会判断为相等,但如果是其他特殊对象则无法正确判断
因此JSON.stringify()的方式只适合简单的、没有特殊属性、无循环引用的对象比较场景,复杂场景不建议使用。
不同场景的选择建议
在实际开发中,可以根据需求选择合适的判断方式:
- 如果只需要比较对象的第一层属性,优先使用浅比较,性能更高
- 如果需要比较完整的对象内容,且对象结构复杂,使用深比较函数,根据是否需要支持特殊对象选择基础版或增强版
- 如果是简单的无嵌套、无特殊属性的对象,临时测试可以使用
JSON.stringify()的方式,但生产环境不推荐 - 如果项目中使用了lodash等工具库,可以直接使用lodash的
_.isEqual方法,该方法已经处理了各种边界场景,可靠性更高
JavaScript对象相等判断深比较浅比较JSON_stringify修改时间:2026-05-29 23:25:33