SuperDiff:提供详细差异信息的 JS diff 工具

双11提前购!买周边/年卡,一键领4重福利! 送200元神券包+10%红包返利+最高10年VIP!还能抽iPhone18Pro!仅限1次,速抢>> 阅读详情

微信搜索“好朋友乐平”关注公众号。


在这里插入图片描述

Superdiff 是一个专门用于处理对象和数组差异比较的工具库。在日常的开发工作中,我们经常会遇到需要比较两个对象或者数组是否相同,以及找出它们之间具体差异的场景。例如,在前端开发中,当我们需要更新页面数据时,就需要知道哪些数据发生了变化;在后端开发中,数据的同步和更新也离不开对数据差异的精确判断。Superdiff 正是为了解决这些问题而诞生的。

丰富的功能特性

Superdiff 提供了一系列强大的功能,让我们来逐一了解。

getObjectDiff(prevObject, nextObject)

import { getObjectDiff } from "@donedeal0/superdiff";

这个函数可以比较两个对象,并返回每个值及其可能的子值的差异。它对任何值类型的深度嵌套对象都提供了支持。想象一下,你有一个复杂的配置对象,在不同的环境下可能会有细微的变化。使用 getObjectDiff 函数,你可以轻松地找出这些变化,而无需手动逐行比较。这不仅节省了时间,还大大降低了出错的可能性。

getListDiff(prevList, nextList)

// Returns a complete diff of two arrays
getListDiff(prevList, nextList)

对于数组的比较,getListDiff 函数可以帮助我们获取两个数组之间的完整差异。在处理列表数据时,我们经常需要知道哪些元素被添加、删除或修改了。这个函数就像是一个智能的小助手,能够准确地告诉你这些信息。比如在一个待办事项列表应用中,当用户对列表进行操作后,我们可以使用 getListDiff 来更新数据库中的数据,确保数据的一致性。

streamListDiff(prevList, nextList, referenceProperty)

// Streams the diff of two object lists, ideal for large lists and maximum performance
streamListDiff(prevList, nextList, referenceProperty)

当我们需要处理大型列表时,传统的比较方法可能会导致性能问题。而 streamListDiff 函数则采用了流式处理的方式,特别适合处理大型列表,能够提供最大的性能优化。它可以逐步输出差异信息,而不是一次性加载整个列表进行比较。这就好比是喝水,我们可以一口一口地喝,而不是一下子把整杯水都灌下去。这种方式不仅减少了内存的占用,还提高了处理速度。

isEqual(dataA, dataB)

import { isEqual } from "@donedeal0/superdiff";

在很多情况下,我们只需要知道两个值是否相等,而不需要详细的差异信息。isEqual 函数就可以满足这个需求,它能够快速判断两个值是否相等。这在数据验证和条件判断中非常有用。比如在表单提交时,我们可以使用 isEqual 来检查用户输入的数据是否与之前保存的数据相同,从而决定是否需要更新数据库。

isObject(data)

import { isObject } from "@donedeal0/superdiff";

有时候,我们需要判断一个值是否是对象。isObject 函数就可以帮助我们轻松完成这个任务。在编写一些通用的工具函数时,这个函数可以帮助我们进行类型检查,避免出现意外的错误。

安装

npm install @donedeal0/superdiff

Diff 示例

输入:

getObjectDiff(
  {
    id: 54,
    user: {
      name: "joe",
-     member: true,
-     hobbies: ["golf", "football"],
      age: 66,
    },
  },
  {
    id: 54,
    user: {
      name: "joe",
+     member: false,
+     hobbies: ["golf", "chess"],
      age: 66,
    },
  }
);

输出:

{
      type: "object",
+     status: "updated",
      diff: [
        {
          property: "id",
          previousValue: 54,
          currentValue: 54,
          status: "equal",
        },
        {
          property: "user",
          previousValue: {
            name: "joe",
            member: true,
            hobbies: ["golf", "football"],
            age: 66,
          },
          currentValue: {
            name: "joe",
            member: false,
            hobbies: ["golf", "chess"],
            age: 66,
          },
+         status: "updated",
          diff: [
            {
              property: "name",
              previousValue: "joe",
              currentValue: "joe",
              status: "equal",
            },
+           {
+             property: "member",
+             previousValue: true,
+             currentValue: false,
+             status: "updated",
+           },
+           {
+             property: "hobbies",
+             previousValue: ["golf", "football"],
+             currentValue: ["golf", "chess"],
+             status: "updated",
+           },
            {
              property: "age",
              previousValue: 66,
              currentValue: 66,
              status: "equal",
            },
          ],
        },
      ],
    }

输入:

getListDiff(
  -["mbappe", "mendes", "verratti", "ruiz"],
  +["mbappe", "messi", "ruiz"]
);

输出:

{
      type: "list",
+     status: "updated",
      diff: [
        {
          value: "mbappe",
          prevIndex: 0,
          newIndex: 0,
          indexDiff: 0,
          status: "equal",
        },
-       {
-         value: "mendes",
-         prevIndex: 1,
-         newIndex: null,
-         indexDiff: null,
-         status: "deleted",
-       },
-       {
-         value: "verratti",
-         prevIndex: 2,
-         newIndex: null,
-         indexDiff: null,
-         status: "deleted",
-       },
+       {
+         value: "messi",
+         prevIndex: null,
+         newIndex: 1,
+         indexDiff: null,
+         status: "added",
+       },
+       {
+         value: "ruiz",
+         prevIndex: 3,
+         newIndex: 2,
+         indexDiff: -1,
+         status: "moved",
+        },
      ],
    }

输入:

const diff = streamListDiff(
  [
    -{ id: 1, name: "Item 1" },
    { id: 2, name: "Item 2" },
    { id: 3, name: "Item 3" },
  ],
  [
    +{ id: 0, name: "Item 0" },
    { id: 2, name: "Item 2" },
    +{ id: 3, name: "Item Three" },
  ],
  "id",
  { chunksSize: 2 }
);

输出:

diff.on("data", (chunk) => {
      // first chunk received (2 object diffs)
      [
+       {
+         previousValue: null,
+         currentValue: { id: 0, name: 'Item 0' },
+         prevIndex: null,
+         newIndex: 0,
+         indexDiff: null,
+         status: 'added'
+       },
-       {
-         previousValue: { id: 1, name: 'Item 1' },
-         currentValue: null,
-         prevIndex: 0,
-         newIndex: null,
-         indexDiff: null,
-         status: 'deleted'
-       }
      ]
    // second chunk received (2 object diffs)
      [
        {
          previousValue: { id: 2, name: 'Item 2' },
          currentValue: { id: 2, name: 'Item 2' },
          prevIndex: 1,
          newIndex: 1,
          indexDiff: 0,
          status: 'equal'
        },
+       {
+         previousValue: { id: 3, name: 'Item 3' },
+         currentValue: { id: 3, name: 'Item Three' },
+         prevIndex: 2,
+         newIndex: 2,
+         indexDiff: 0,
+         status: 'updated'
+       },
     ]
});

diff.on("finish", () => console.log("The full diff is available."))
diff.on("error", (err) => console.log(err))

底层实现

diff 的实现主要是通过比较两个对象或数组的结构和内容来确定它们之间的差异。以下是实现原理的简要概述:

  1. 类型检查:首先,函数会检查输入的两个对象或数组的类型。如果它们的类型不同,则直接返回不相等。

  2. 数组比较:如果输入是数组,函数会检查它们的长度是否相同。如果长度不同,则返回不相等。如果长度相同,函数会根据 ignoreArrayOrder 选项决定是否忽略数组的顺序进行比较。

  3. 对象比较:对于对象,函数会遍历对象的每个属性,递归地比较每个属性的值。如果属性的值是对象,则会进一步调用 diff 函数进行深度比较。

  4. 状态标记:在比较过程中,函数会为每个属性或元素生成一个状态标记(如 “added”、“deleted”、“updated”、“equal”),以便在最终结果中返回。

  5. 结果构建:最后,函数会将所有的差异收集到一个数组中,并返回这个数组,表示两个输入之间的差异。

function isEqual(t, e, options = { ignoreArrayOrder: false }) {
  if (typeof t !== typeof e) return false;
  if (Array.isArray(t) && Array.isArray(e)) {
    if (t.length !== e.length) return false;
    return options.ignoreArrayOrder
      ? t.every((item) =>
          e.some((i) => JSON.stringify(i) === JSON.stringify(item))
        )
      : t.every(
          (item, index) => JSON.stringify(item) === JSON.stringify(e[index])
        );
  }
  if (typeof t === "object") {
    return JSON.stringify(t) === JSON.stringify(e);
  }
  return t === e;
}

function getObjectDiff(t, e, options) {
  let diff = [];
  for (let [key, value] of Object.entries(t)) {
    if (!(key in e)) {
      diff.push({
        property: key,
        previousValue: value,
        currentValue: undefined,
        status: "deleted",
      });
    } else if (!isEqual(value, e[key], options)) {
      diff.push({
        property: key,
        previousValue: value,
        currentValue: e[key],
        status: "updated",
      });
    }
  }
  for (let key in e) {
    if (!(key in t)) {
      diff.push({
        property: key,
        previousValue: undefined,
        currentValue: e[key],
        status: "added",
      });
    }
  }
  return diff;
}

微信搜索“好朋友乐平”关注公众号。

github原文地址

JavaScript差异比较组件详解及应用 在现代软件开发中,Diff算法被广泛应用在文件比较、版本控制以及前端框架中来实现高效的更新检测和差异化显示。算法的核心在于比较两个序列之间的差异,无论是代码文件、文本数据还是DOM树。本章节将为读者提供对Diff算法的基础理解,从而为进一步探索特定库如jsdifflib的实现与优化打下坚实基础。Diff算法的种类繁多,包括经典的逐字符比较的Levenshtein距离算法、快速的Myers差异算法,以及更贴近前端实际应用场景的树结构比较算法。这些算法在效率和实现复杂度上各有优劣,适用于不同场景。 阅读详情

相关推荐

html差异化比较工具(网页版)

网页版差异化对比,网页版差异化比较工具。html差异化比较功能,支持html标签比较。 目前的很多工具都是C/S模式,没有网页版。上传的工具可以直接嵌入到项目,进行html内容差异化比较。

vue.js获取object对象的值_比较 JavaScript 对象的四种方式

每日前端夜话第351篇作者:疯狂的技术宅正文共:2400字预计阅读时间:7 分钟比较 JavaScript 中的值非常简单,只需用相等运算符即可,例如严格相等运算符:1'a'==='c';//=>false21===1;//=>true但是对象却有结构化的数据,所以比较起来比较困难。在本文中,你将学习如何正确比较 JavaScript 中的对象。...

weixin_34086714的博客 5728

python实现语音信号的分帧、加窗、预处理

语音信号实现分帧、加窗、预处理音频文件读取预加重分帧加窗 音频文件读取 librosa是非常强大的python语音信号处理库。 读取音频: 使用语句librosa.load(path, sr=22050, mono=True, offset=0.0, duration=None)读取音频文件,默认的采样率是22050,若要保留音频的原始采样率,使用sr=None。 其中: path:表示音频文件的路径 sr:表示采样率 mono:bool,是布尔类型,表示是否将信号转换为单声道 offset:float,后

weixin_45272908的博客 1万+

javascript获取两个对象之间的差异不同

注意:一般来讲正常人只有一个对象或者没有对象(

zhichaogong的博客 2140

深入学习FIFO

深入理解FIFO、同步FIFO和异步FIFO、FIFO设计的难点以及FIFO深度计算

好好学习,天天向上 2636

从INCA到Excel:手把手教你移植汽车标定数据的查表插值算法(附源码)

本文详细介绍了如何将汽车标定数据从INCA平台移植到Excel,实现查表插值算法的完整迁移。通过解析INCA MAP数据结构,设计Excel环境下的双线性插值算法,并提供VBA和C#两种实现方案,帮助工程师高效处理标定数据。文章包含实用代码示例和性能优化技巧,适用于ECU开发与标定场景。

weixin_29313239的博客 404

【算法设计】javascript 比较两个不同的对象

比对两个数据结构相同的对象并返回两个对象中值不同的键 BFS版 var time = new Date() var obj1 = { a: 1, // b: { c: 1, // d: 2 // }, e: [1, 2, 3], // 每个都是 f: '123', // g: { h: 3, // i: 5, // j: { k: 1, //

SDUzzy的博客 1356

微信小程序一键登录和临时code用JWT进行微信用户授权

2、跨域进行调用接口时候,唯一标识UnionID和会话密钥 session_key如果还是用的我自己的,会出现无法调用微信服务器接口,就需要将唯一标识和会话密钥换成前端的,才可以,我自己认为这样很不合理,暂时还没有找到原因。2、能够获取到openId,但是也只能获取到openid,无法获取用户的相关信息,经过查阅官网发现,现在微信那边已经将用户信息加密,需要调用提供的接口进行解密然后获取用户数据,问题原因已经找到解决方法,还未即使更改。1、我这是一台电脑实现的前端调用后端接口,不用考虑跨域的问题。

qq_67653492的博客 5703

用原生JavaScript打造极简名单比对工具:3分钟实现数据对比神器

用原生JavaScript打造极简名单比对工具:3分钟实现数据对比神器

一起coding,一起嗨。 1017

SpringBoot系列之实现一个AI聊天助手

本文介绍了基于Spring Boot框架实现的AI聊天助手项目。该项目使用Spring Boot 3.2.3、Spring AI 1.0.0-M5等技术栈,集成DeepSeek-R1-Distill-Llama-8B模型实现智能对话功能。文章详细介绍了项目配置流程、运行方式和核心代码实现,包括ChatMessage模型类和服务类ChatService的关键功能,如消息处理、历史记录管理和AI响应获取等。读者可通过提供的GitHub链接获取完整代码,快速搭建自己的AI聊天应用。

Nicky's blog 1435

37、半导体硅材料中的缺陷与吸杂技术解析

本文系统解析了半导体硅材料中的缺陷形成机制及其对电子器件性能的影响,重点探讨了生长和工艺诱导缺陷、表面与内部微缺陷的起源与特征。文章详细阐述了吸杂技术的原理、过程及在集成电路和太阳能电池制造中的应用,强调通过氧行为调控和热处理优化实现缺陷控制。同时介绍了吸杂效果的评估方法,并展望了未来新型吸杂技术的发展趋势,为提升半导体器件性能和制造良率提供理论支持和技术路径。

mongodb5scout的博客 156

JavaScript 利用差集写一个自己的对比小工具

在工作中需要每周统计人员提交材料情况又不想一个一个复制黏贴查找只好写一个小工具帮自己查找谁没提交材料 先把页面搞一搞 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=devi

qq_42249813的博客 334

024、反激变换器的短路保护设计

本文详细探讨了反激变换器短路保护的设计要点与实践经验。作者通过实际案例分析了短路时反激拓扑的电流特性,指出初级峰值电流限制是最基础的保护手段,但需配合打嗝模式使用。文章重点剖析了打嗝模式设计的三个关键陷阱:频率设定、退出条件和软启动衔接。同时强调次级侧辅助保护、变压器参数优化、环路响应协调的重要性,并比较了自恢复与锁死方案的适用场景。最后提出实测验证的四个关键点和设计经验:不盲信芯片手册、保护电路独立设计、充分留有余量、进行破坏性测试。全文以工程实践为导向,为反激电源的可靠短路保护提供了系统性解决方案。

Jack010169的博客 228

比较 JavaScript 对象的四种方式

比较JavaScript中的原始值非常简单。只需使用任何一种可用的相等运算符即可,例如严格相等运算符: 'a' === 'c'; // => false 1 === 1; // => true 但是对象却有结构化数据,所以比较起来比较困难。在本文中,你将学习如何正确比较JavaScript中的对象。 1. 引用比较 JavaScript提供了 3 种对值进行比较的方法: 严格相等运算符=== 宽松相等运算符== Object.is()函数 当使用上述...

高先生的猫 1147

基于AI的智能开发环境—Trae在Web开发中的应用实战与性能评估【Trae项目实战】

Trae 是一款与 AI 深度集成的开发工具,提供智能问答、代码自动补全和基于 Agent 的 AI 自动编程能力,极大提升开发效率。它具备完备的 IDE 功能,如代码编写、项目管理和源代码管理等,同时还具备强大的 AI 助手,能够提供智能问答、实时代码建议、代码片段生成等服务。开发者可以通过自然语言与 AI 协作,从 0 到 1 开发项目,AI 会根据需求自动生成代码或创建文件。

一键难忘的博客 3万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Json数据的对比工具,对比库(含js在线对比工具,.net 的jsondiffer包)

1)如果是偶尔手工对比两个值,可以借助json的在新对比工具: 在线地址:json在线对比工具 2)如果是.net 中对比两个json的差异. 建议使用:NuGet Gallery | JsonDiffer 0.2.0 https://www.nuget.org/packages/JsonDiffer ...

key12315的专栏 1742

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

终极指南:如何快速部署Wan2.1-Fun-V1.1-1.3B-InP AI视频生成模型Docker环境

Wan2.1-Fun-V1.1-1.3B-InP是一款由阿里巴巴PAI团队开发的先进AI视频生成模型,专注于图像到视频转换功能。这个容器化AI视频生成环境让开发者能够轻松搭建专业的视频生成平台,无需复杂的依赖配置即可开始创作AI视频内容。本文将为您提供完整的Docker部署教程,帮助您快速搭建这个强大的AI视频生成环境。 ## 🚀 为什么选择Docker部署AI视频生成环境? Docker容

gitblog_01150的博客 663

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

掌握C++高级编程:19章动态类型与联合类型终极指南

想要成为C++编程高手?C++ Primer第十九章为你揭晓专业编程技巧!本章深入讲解**动态类型转换**和**联合类型**等高级特性,帮助你构建更安全、更高效的C++应用程序。😊 ## 什么是C++动态类型转换? **动态类型转换**是C++运行时类型识别(RTTI)的核心功能,它允许程序在运行时安全地处理类型转换。通过分析[ch19/ex19_3_4.cpp](https://link.

gitblog_01002的博客 574

纯js对比excel小工具

未来,你可以在此基础上扩展更多功能,如导出对比结果、支持更多文件类型等,以满足更广泛的应用需求。

随笔 2148

JS比较前后两个数组对象的差异

js数组方法,比较两个数组对象前后的差异

如诗 1424

Electrobun深度剖析:Bun与Zig技术融合如何重塑桌面应用开发范式

Electrobun是一个革命性的桌面应用开发框架,它巧妙地将Bun的现代JavaScript运行时与Zig的系统级编程能力相结合,为开发者提供构建超快速、轻量级跨平台桌面应用的全新解决方案。这个框架不仅解决了传统Electron应用体积庞大、启动缓慢的痛点,更通过创新的架构设计实现了原生级别的性能表现,同时保留了Web技术栈的开发便利性。其核心优势在于极致的性能优化、微小的应用体积和卓越的开发体

gitblog_00093的博客 458

【亲测免费】 jsdiff:JavaScript文本差异比较神器

`jsdiff` 是一个强大的JavaScript库,用于在文本字符串之间进行差异比较。它基于Myers提出的O(ND)算法,可以高效地计算出两个文本块的差异,并以列表形式返回这些差异。你可以通过**[在线演示](https://kpdecker.github.io/jsdiff)**来快速了解其效果。 ## 项目技术分析 `jsdiff` 提供了一系列方法来处理不同级别的文本差异比较: -...

gitblog_00085的博客 3383

推荐一个好组件Javascript文本比较工具

您的项目上有没有遇到需要在前端显示并比较两个不同版本的文本文件, 希望它像winmerge, 或eclipse的svn比较工具那样标注不同的地方? 我找到了, 分享给大家吧. 最近项目上需要一个类似cvs/svn文本比较工具, 把左右两个文本中不一样的部分标出来. 最后找到了这个:mergely: http://www.mergely.com/ 上个图看看效果吧: 是不是您想要的? 支持的格...

dawuafang 1983

js新旧数据比较器-ComparatorsUtils

在开发过程当中也许会遇到新旧数据的比较,把操作过的数据传给后端,比如:新增的,修改过的,删除的。 接下来看代码: /** * 此工具为数据比较器, * 可返回新增的数据,修改的数据,删除的数据,以及三种数据 * 并将这些操作过的数据都添加上标记 operationType 1新增 2修改 3删除 * 后端可根据标记类型进行操作 */ /** * @param willUploadData 将要上传的数据 * @param rawData 源数据(旧数据) * @param ret

jsyxiaoba的博客 1128

在线JSON差异比较工具:BlitLabs在线JSON Diff

在线JSON差异比较工具:BlitLabs在线JSON Diff 项目地址:https://gitcode.com/gh_mirrors/on/online-json-diff 在日常开发和数据分析中,我们常常需要对比两个JSON对象的差异,以找出它们之间的微妙变化或错误。为此,提供了一个高效且直观的解决方案。这个开源项目利用现代Web技术,帮助开发者轻松地完成JSON对象的比较,并且它完全免费、...

gitblog_00073的博客 2902

【亲测免费】 推荐一款强大的图片对比工具:JuxtaposeJS

在数字媒体的世界中,图像的对比是一种强大的叙事手段。它可以帮助读者更直观地理解变化和差异。今天,我们向您推荐一个专为此目的设计的开源项目——[JuxtaposeJS][https://juxtapose.knightlab.com],这是一个简洁而强大的工具,用于创建前后对比的图像滑块。 ## 项目介绍 JuxtaposeJS是一个简单易用的开源工具,只需提供两张图片的URL,就能自动生成交互

gitblog_00011的博客 1595
上一篇: 必看!wechat-article-exporter:轻松批量下载公众号文章
下一篇: 前端技术月刊-2025.2
王乐平
王乐平 领域专家: 前端开发技术领域 领域专家: 前端开发技术领域
博客等级 码龄11年 2444粉丝 192原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王乐平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值