数据比较是一个在 Web 开发中非常普遍的操作,比如对比两个版本之间的差异,提取新增或者删除的数据,并对其进行进一步的操作。在前端中,我们通常使用 JavaScript 对象或者数组来存储数据,然后通过手写方法来进行这些数据操作。但是如果数据量较大或者操作比较复杂时,会显得很繁琐。这时我们可以使用现有的 npm 包,比如 diff-object-array,来帮助我们快速地完成这些操作。
diff-object-array 是什么
diff-object-array 是一个 npm 包,用于比较两个数组或对象的差异,并返回它们之间的差异结果。这个库支持数组和对象的比较,可以返回新增和删除的元素,以及原先存在但属性值改变的元素。
安装
使用 npm 安装 diff-object-array:
npm install diff-object-array
使用方法
我们通过一个简单的例子来演示 diff-object-array 的用法。
首先,我们定义两个对象:
-- -------------------- ---- ------- ----- ------ - - ----- ------ ---- --- ------- ------- -- ----- ------ - - ----- -------- ------ ------------------ ------- ------- --
假设我们需要找出两个对象的差异,可以这样使用 diff-object-array:
const diff = require('diff-object-array'); const result = diff(oldObj, newObj); console.log(result.added); // => [{ email: 'jerry@gmail.com' }] console.log(result.removed); // => [{ name: 'Tom' }] console.log(result.changed); // => [{ key: 'name', oldVal: 'Tom', newVal: 'Jerry' }]
接下来我们讲解一下 diff-object-array 的源码和实现原理。
diff-object-array 的实现原理
diff-object-array 的实现原理可归纳为如下三步:
- 将两个对象分别拆分为属性数组和属性值数组;
- 将这两个属性数组进行比较,找出其中差异的元素;
- 根据差异元素的情况,构造出差异结果对象。
下面我们逐一讲解这三步。
1. 拆分为属性数组和属性值数组
diff-object-array 是通过 Object.keys()、Array.prototype.forEach 和 for...in 等方法来遍历对象,将其拆分为属性数组和属性值数组。
-- -------------------- ---- ------- -------- ------------------ ---- ------ ------- - ----- - ----- ------ - - ------- -- ----------------- - --------------- -- ------- ----- --- ----------- - ------------------- - ---- - ------------------ -------------- ------- -- -- -- - ------------------ -------------- -- -------- --- - - ---- - --------------- ------------------- - - -------- -------------------- - ----- ---- - --- ----- ------ - --- ------------ ------- ---- ------ -- - ------------------ ---- ------ - ----- ------ --- --- ------ ------ -------- - -------- ------------------- - ----- ---- - --- ----- ------ - --- ------------------- ------ -- - ---------------------------- ------------------ ----------------- ------ - ----- ------ --- --- ------ ------ -------- -
上面这个代码块说明了 decomposeObject 和 decomposeArray 函数是怎么将对象和数组进行拆分的。
当对象或者数组的属性值也是对象或者数组时,我们需要递归地将其拆分,并且通过拼接键名的方式得到完整的键名。
2. 属性数组的比较
diff-object-array 的比较主要是在 compareKeys 这个函数里完成的。
这个函数会遍历两个属性数组,找到它们之间的差异。
-- -------------------- ---- ------- -------- -------------------- -------- - ----- ----- - --- ----- ------- - --- ----- ------- - --- --------------------- ------ -- - ----- -------- - --------------------- -- --------- --- --- - -------------- - ----- - --- --------------------- ------ -- - ----- -------- - --------------------- -- --------- --- --- - ------------ - ----- - ---- -- -------------------- - -------------- ---- --------- --------- ----- --- - --- ------ - ------ ----- ----------- ------ -- ------ ----- --- --------- -------- ------ -- ---------------- -------- ------- ----------- ------ -- ------ ----- --- --------- -------- ------ -- ---------------- -------- -------------------- -- -- ---- ----------- ------- --------------------------- ------- --------------------------- ---- -- -
这里将属性数组分为三种类型:
- added:新增元素的数组;
- removed:删除元素的数组;
- changed:改变元素的数组。
当数组中某一个元素既没有在旧数组中出现过,也没有在新数组中出现过时,被认为是新增元素;当元素只在旧数组中出现过,没有在新数组中出现过时,认为是删除元素;当元素同时在新旧数组中出现时,不被认为增或删,而是判断是否改变。
3. 构造差异结果对象
最后,我们通过 diffKeys 函数将比较结果转换为差异对象。
-- -------------------- ---- ------- -------- ----------------- ---------- -------- ---------- - ----- - ------ -------- ------- - - -------------------- --------- ----- ------ - --- -- -------------- - ------------ - ------------------------------ ------------ - -- ---------------- - -------------- - -------------------------------- ------------ - -- ---------------- - ----- ----------- - --- ------------------ ---- ------- ------ -- -- - ----- ------ ------- - ------------------ -------- ------------------ ---- ----- ------ --- --- -------------- - ------------ - ------ ------- -
这个函数将新增、删除、改变元素的差异集合起来,构建出一个差异结果对象,其中的每个差异元素都是完整的对象或者数组项,而不是简单的 key-value 形式的相差数值。
结论
diff-object-array 是一个非常实用的 npm 包,能够帮助前端工程师快速地进行数据比较,获取差异结果。该包的底层代码库很简洁,使用方法也非常简单。我们希望,在实际的开发过程中,能够广泛运用 diff-object-array 并理解其底层原理,从而更加高效地进行项目开发。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/60055fd881e8991b448dd634