侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1824 篇文章
  • 累计收到 0 条评论

实现一个深度比较两个对象是否相等的函数

2025-12-12 / 0 评论 / 6 阅读

题目

实现一个深度比较两个对象是否相等的函数

信息

  • 类型:问答
  • 难度:⭐⭐

考点

对象比较,递归算法,类型判断,边界条件处理

快速回答

实现深度对象比较需要:

  • 处理基本类型和引用类型的差异
  • 递归比较嵌套对象和数组
  • 特殊边界处理(日期、正则等)
  • 避免循环引用导致的无限递归
  • 考虑构造函数一致性和原型链
## 解析

深度比较两个对象需要全面考虑JavaScript的各种数据类型和边界情况。

核心实现原理

递归遍历对象属性,分层比较:

  1. 首先通过===比较基本类型
  2. 检查是否为null或非对象类型
  3. 比较构造函数和原型链
  4. 递归比较嵌套属性

代码示例

function deepEqual(obj1, obj2, seen = new WeakMap()) {
  // 基本类型直接比较
  if (obj1 === obj2) return true;

  // 处理null和undefined
  if (obj1 == null || obj2 == null || typeof obj1 !== 'object' || typeof obj2 !== 'object') {
    return obj1 === obj2;
  }

  // 循环引用检测
  if (seen.has(obj1) && seen.get(obj1) === obj2) return true;
  seen.set(obj1, obj2);

  // 比较构造函数
  if (obj1.constructor !== obj2.constructor) return false;

  // 特殊对象处理
  if (obj1 instanceof Date) return obj1.getTime() === obj2.getTime();
  if (obj1 instanceof RegExp) return obj1.toString() === obj2.toString();

  // 数组比较
  if (Array.isArray(obj1)) {
    if (obj1.length !== obj2.length) return false;
    return obj1.every((item, i) => deepEqual(item, obj2[i], seen));
  }

  // 对象属性比较
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  if (keys1.length !== keys2.length) return false;

  return keys1.every(key => {
    return obj2.hasOwnProperty(key) && 
           deepEqual(obj1[key], obj2[key], seen);
  });
}

最佳实践

  • 使用WeakMap跟踪比较过的对象避免循环引用
  • 优先比较构造函数提高效率
  • 单独处理DateRegExp等特殊对象
  • 使用Object.keys()确保只比较自身属性

常见错误

  • 未处理循环引用导致栈溢出
  • 忽略构造函数差异(如[]{}
  • 未考虑特殊对象的时间戳比较
  • 使用for-in遍历会包含原型链属性
  • 未处理Symbol类型属性

扩展知识

  • 循环引用检测:通过WeakMap存储已比较对象,键值弱引用避免内存泄漏
  • Symbol属性处理:可通过Object.getOwnPropertySymbols()补充
  • 性能优化:复杂对象可先进行浅比较(Object.is()
  • 边界情况NaN+0/-0需特殊处理(本例中由===处理)