一、基础概念:对象相等的类型
- 值相等(Value Equality):对象属性值相同,不要求引用相同
- 引用相等(Reference Equality):两个变量指向同一内存地址
二、引用相等:简单判断
1. === 或 ==(基本类型适用)
const a = { x: 1 };
const b = a;
console.log(a === b);
const c = { x: 1 };
console.log(a === c);
- 注意:
== 会类型转换,=== 严格比较,对象比较需用 ===
三、值相等:深度比较方案
1. 浅拷贝 + 递归比较(手动实现)
function isDeepEqual(obj1, obj2) {
if (obj1 === obj2) return true;
if (obj1 === null || obj2 === null) return false;
if (typeof obj1 !== 'object' || typeof obj2 !== 'object') return false;
if (Array.isArray(obj1) && Array.isArray(obj2)) {
if (obj1.length !== obj2.length) return false;
return obj1.every((val, i) => isDeepEqual(val, obj2[i]));
}
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
return keys1.every(key => isDeepEqual(obj1[key], obj2[key]));
}
- 缺陷:无法处理循环引用(如
obj.a = obj)
2. JSON序列化方案(简单场景)
function isShallowEqual(obj1, obj2) {
return JSON.stringify(obj1) === JSON.stringify(obj2);
}
- 局限:
- 无法处理函数、RegExp等非JSON类型
- 会忽略
undefined和null的差异
- 无法检测循环引用
3. 第三方库:Lodash _.isEqual
import { isEqual } from 'lodash';
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { a: 1, b: { c: 2 } };
console.log(isEqual(obj1, obj2));
- 优势:
- 支持循环引用检测
- 处理函数、Date等特殊类型
- 性能优化(短路比较、缓存等)
四、问题
1. 问:为什么 {a:1} == {a:1} 返回 false?
- 答:
== 和 === 比较对象时,比较的是内存引用而非值
- 两个对象是独立创建的,引用地址不同,故返回false
2. 问:如何判断两个数组是否相等?
五、性能优化与特殊场景
1. 快速比较:先检查引用和长度
function optimizedEqual(obj1, obj2) {
if (obj1 === obj2) return true;
if (Object.keys(obj1).length !== Object.keys(obj2).length) return false;
}
2. 循环引用处理
function deepEqualWithCycle(obj1, obj2, visited = new WeakMap()) {
if (obj1 === obj2) return true;
if (visited.has(obj1)) return visited.get(obj1) === obj2;
visited.set(obj1, obj2);
}
3. React场景:浅比较优化
import { shallowEqual } from 'react-redux';
shouldComponentUpdate(nextProps) {
return !shallowEqual(this.props, nextProps);
}
六、方案对比与场景选择
| 方案 | 优点 | 缺点 | 适用场景 |
|---|
=== | 性能极高 | 仅比较引用 | 基本类型或引用相等 |
| JSON序列化 | 代码简洁 | 功能有限 | 简单对象浅比较 |
| 手动递归 | 可控性强 | 需处理循环引用 | 自定义场景 |
| Lodash isEqual | 功能全面 | 引入额外依赖 | 通用场景 |