导读:本期聚焦于小伙伴创作的《JavaScript中如何判断两个对象是否相等?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中如何判断两个对象是否相等?》有用,将其分享出去将是对创作者最好的鼓励。

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

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

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。