JavaScript中如何比较两个JSON数组并提取差异数据

来源:AI大模型作者:叶知晏头衔:草根站长
导读:本期聚焦于小伙伴创作的《JavaScript中如何比较两个JSON数组并提取差异数据》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《JavaScript中如何比较两个JSON数组并提取差异数据》有用,将其分享出去将是对创作者最好的鼓励。

在JavaScript开发中,经常会遇到需要对比两个JSON数组的场景,比如前端获取到的本地缓存数据和最新的服务端数据对比,或者表单修改前后的数据差异校验,核心需求就是找出两个数组中不同的元素,包括仅存在于第一个数组的新增元素、仅存在于第二个数组的删除元素,以及两个数组中都存在但属性有变化的数据。

JavaScript中如何比较两个JSON数组并提取差异数据

基础对比:基于唯一标识提取差异

如果JSON数组中的每个元素都有唯一标识字段,比如id,那么对比逻辑会简单很多,我们可以通过唯一标识快速判断元素的归属。

提取仅存在于第一个数组的元素

思路是先收集第二个数组所有唯一标识,再遍历第一个数组过滤出标识不在第二个数组中的元素。

// 定义两个待对比的JSON数组
const arr1 = [
  { id: 1, name: '张三', age: 20 },
  { id: 2, name: '李四', age: 22 },
  { id: 3, name: '王五', age: 25 }
];
const arr2 = [
  { id: 2, name: '李四', age: 23 },
  { id: 3, name: '王五', age: 25 },
  { id: 4, name: '赵六', age: 28 }
];

// 提取arr2中所有的id集合
const arr2Ids = new Set(arr2.map(item => item.id));
// 仅存在于arr1中的元素
const onlyInArr1 = arr1.filter(item => !arr2Ids.has(item.id));
console.log('仅存在于第一个数组的元素:', onlyInArr1);

提取仅存在于第二个数组的元素

同理,我们收集第一个数组的唯一标识,再过滤第二个数组即可。

// 提取arr1中所有的id集合
const arr1Ids = new Set(arr1.map(item => item.id));
// 仅存在于arr2中的元素
const onlyInArr2 = arr2.filter(item => !arr1Ids.has(item.id));
console.log('仅存在于第二个数组的元素:', onlyInArr2);

深度对比:处理属性变化的差异

如果数组元素没有唯一标识,或者需要对比元素属性的变化,就需要用到深度比较的方法。这里我们可以使用JSON.stringify做简单的序列化对比,也可以使用更严谨的深度比较函数。

使用JSON.stringify做简单对比

这种方式适合数组元素结构比较简单的场景,注意如果对象属性顺序不同,JSON.stringify的结果会不一样,可能导致误判。

// 简单深度比较函数,使用JSON.stringify实现
function isSameObj(obj1, obj2) {
  return JSON.stringify(obj1) === JSON.stringify(obj2);
}

// 找出arr1中和arr2所有元素都不相同的元素
const diffInArr1 = arr1.filter(item1 => {
  return !arr2.some(item2 => isSameObj(item1, item2));
});
console.log('arr1中和arr2不同的元素:', diffInArr1);

自定义深度比较函数

如果对象属性顺序可能不同,或者需要处理更复杂的数据类型,我们可以自定义深度比较函数。

// 自定义深度比较函数
function deepEqual(obj1, obj2) {
  // 基本类型直接比较
  if (obj1 === obj2) return true;
  // 类型不同直接返回false
  if (typeof obj1 !== typeof obj2) return false;
  // 处理null的情况
  if (obj1 == null || obj2 == null) return false;
  // 处理数组
  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])) return false;
    }
    return true;
  }
  // 处理对象
  if (typeof obj1 === 'object' && typeof obj2 === 'object') {
    const keys1 = Object.keys(obj1);
    const keys2 = Object.keys(obj2);
    if (keys1.length !== keys2.length) return false;
    for (const key of keys1) {
      if (!deepEqual(obj1[key], obj2[key])) return false;
    }
    return true;
  }
  return false;
}

// 使用自定义深度比较函数找差异
const diffArr1 = arr1.filter(item1 => {
  return !arr2.some(item2 => deepEqual(item1, item2));
});
const diffArr2 = arr2.filter(item2 => {
  return !arr1.some(item1 => deepEqual(item1, item2));
});
console.log('arr1中独有的元素:', diffArr1);
console.log('arr2中独有的元素:', diffArr2);

提取属性变化的差异数据

如果我们不仅想知道元素是否存在差异,还想知道具体哪些属性发生了变化,可以结合唯一标识和深度比较实现。

// 找出两个数组中都存在但属性有变化的元素
const changedItems = [];
arr1.forEach(item1 => {
  const target = arr2.find(item2 => item2.id === item1.id);
  if (target && !deepEqual(item1, target)) {
    // 找出变化的属性
    const changedKeys = {};
    Object.keys(item1).forEach(key => {
      if (item1[key] !== target[key]) {
        changedKeys[key] = {
          oldValue: item1[key],
          newValue: target[key]
        };
      }
    });
    changedItems.push({
      id: item1.id,
      changes: changedKeys
    });
  }
});
console.log('属性变化的元素:', changedItems);

不同场景的方案选择

我们可以根据实际场景选择不同的对比方案:

  • 如果数组元素有唯一标识,优先使用基于唯一标识的对比方案,时间复杂度低,效率更高
  • 如果元素没有唯一标识且结构简单,可以使用JSON.stringify的序列化对比
  • 如果元素结构复杂、属性顺序可能不一致,建议使用自定义深度比较函数
  • 如果需要知道具体属性变化内容,结合唯一标识和属性遍历的方案实现

以上几种方案覆盖了大部分JavaScript中对比JSON数组并提取差异的场景,开发者可以根据实际需求选择合适的实现方式,也可以将对应的函数封装成工具函数方便后续复用。

JavaScriptJSON数组数组比较差异提取修改时间:2026-06-19 02:57:42

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