0

0

JavaScript 深层对象差异检测:精准提取键值变更的实用教程

霞舞

霞舞

发布时间:2026-01-27 17:55:01

|

287人浏览过

|

来源于php中文网

原创

javascript 深层对象差异检测:精准提取键值变更的实用教程 - php中文网

本文详解如何正确比较含嵌套数组/对象的 JavaScript 数据结构,避免因引用相等性导致的误判,提供可复用的深度值比较函数与差异提取逻辑。

在 JavaScript 中,直接使用 === 或 == 比较对象或数组时,实际比对的是内存引用地址,而非内容本身。这意味着即使两个数组结构完全一致(如 [{a: 1}] 和 [{a: 1}]),只要它们是不同实例,比较结果即为 false。这正是原问题中 imagens 和 lotes 被错误标记为“不同”的根本原因——它们是引用类型,而原始函数未做深层值比较。

要精准识别真实的数据变更,必须实现按值比较(value-based comparison),尤其针对嵌套的数组与对象。以下是一个生产就绪的解决方案,包含两个核心部分:

  1. isObjArrayValueEqual:专用于比较元素全为普通对象的数组(支持多层级嵌套对象,但本例暂不递归处理嵌套对象内的嵌套对象;如需完整深比较,建议引入 lodash.isEqual 或自行扩展递归逻辑);
  2. 增强版 getNew:在键级差异检测中,对数组字段调用上述函数,其余类型仍使用严格相等判断。
function isObjArrayValueEqual(arr1, arr2) {
  if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false;
  if (arr1.length !== arr2.length) return false;

  for (let i = 0; i < arr1.length; i++) {
    const obj1 = arr1[i];
    const obj2 = arr2[i];

    // 确保两者均为非 null 对象
    if (typeof obj1 !== 'object' || typeof obj2 !== 'object' || obj1 === null || obj2 === null) {
      return false;
    }

    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) return false;

    // 逐属性比对(仅支持一层对象;若需深度嵌套,请递归调用 isEqual)
    for (const key of keys1) {
      if (obj1[key] !== obj2[key]) return false;
    }
  }
  return true;
}

const getNew = (newObj, oldObj) => {
  // 边界处理:oldObj 为空时直接返回 newObj
  if (Object.keys(oldObj).length === 0 && Object.keys(newObj).length > 0) {
    return newObj;
  }

  const diff = {};
  for (const key in oldObj) {
    // 仅当 newObj 存在该 key 且值不等时进入判断
    if (!(key in newObj)) continue;

    if (oldObj[key] !== newObj[key]) {
      // 对数组类型启用值比较
      if (Array.isArray(oldObj[key]) && Array.isArray(newObj[key])) {
        if (!isObjArrayValueEqual(newObj[key], oldObj[key])) {
          diff[key] = newObj[key];
        }
      } else {
        // 基本类型、null、Date、RegExp 等需额外处理;此处默认按值比较(注意:Date 需用 getTime())
        diff[key] = newObj[key];
      }
    }
  }

  return diff; // 统一返回 diff 对象(空对象表示无差异)
};

使用示例:  

Otter.ai
Otter.ai

一个自动的会议记录和笔记工具,会议内容生成和实时转录

下载

立即学习Java免费学习笔记(深入)”;

const objA = { 
  nome: "Lotes", 
  lotes: [{ lote: "LOte0", loteQtd: "8" }] 
};

const objB = { 
  nome: "Lotes", 
  lotes: [{ lote: "LOte0", loteQtd: "8" }] 
};

console.log(getNew(objA, objB)); // → {}(无差异)

const objC = { 
  nome: "Lotes", 
  lotes: [{ lote: "LOte0", loteQtd: "9" }] 
};

console.log(getNew(objA, objC)); // → { lotes: [...] }

⚠️ 注意事项:  

  • 当前 isObjArrayValueEqual 仅支持数组内纯对象(不含函数、undefined、NaN、Symbol、Date、正则等特殊值)。若数据含这些类型,需扩展比较逻辑(例如:Date 用 getTime(),NaN 用 Number.isNaN() 判断)。
  • 如需完整深比较(包括对象内嵌套对象、Set/Map 等),强烈推荐使用成熟库:  
    npm install lodash.isequal
    import isEqual from 'lodash.isequal';
    // 替换 isObjArrayValueEqual 判定为:isEqual(newObj[key], oldObj[key])
  • 原始函数末尾 return oldObj 易引发歧义(应返回 diff 或 null),已统一改为返回 diff(空对象即无变化),符合“差异即变更”的语义直觉。

掌握引用与值的差异本质,并辅以针对性的比较策略,才能构建出鲁棒的对象差异分析工具——这是状态管理、表单脏检查、API 增量更新等场景的关键基础能力。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

254

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

1089

2024.03.01

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

550

2023.12.01

C++ 高效算法与数据结构
C++ 高效算法与数据结构

本专题讲解 C++ 中常用算法与数据结构的实现与优化,涵盖排序算法(快速排序、归并排序)、查找算法、图算法、动态规划、贪心算法等,并结合实际案例分析如何选择最优算法来提高程序效率。通过深入理解数据结构(链表、树、堆、哈希表等),帮助开发者提升 在复杂应用中的算法设计与性能优化能力。

30

2025.12.22

深入理解算法:高效算法与数据结构专题
深入理解算法:高效算法与数据结构专题

本专题专注于算法与数据结构的核心概念,适合想深入理解并提升编程能力的开发者。专题内容包括常见数据结构的实现与应用,如数组、链表、栈、队列、哈希表、树、图等;以及高效的排序算法、搜索算法、动态规划等经典算法。通过详细的讲解与复杂度分析,帮助开发者不仅能熟练运用这些基础知识,还能在实际编程中优化性能,提高代码的执行效率。本专题适合准备面试的开发者,也适合希望提高算法思维的编程爱好者。

45

2026.01.06

golang map内存释放
golang map内存释放

本专题整合了golang map内存相关教程,阅读专题下面的文章了解更多相关内容。

77

2025.09.05

golang map相关教程
golang map相关教程

本专题整合了golang map相关教程,阅读专题下面的文章了解更多详细内容。

40

2025.11.16

golang map原理
golang map原理

本专题整合了golang map相关内容,阅读专题下面的文章了解更多详细内容。

67

2025.11.17

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 6.1万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 3.4万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号