深潜
深潜 是一个javascript/node.js模块,提供用于确定对象间结构差异的功能,并包括一些用于应用对象间差异的功能.
安装
npm install @bluelovers/deep-diff
可能 v1.0 相容性 :
- 数组中的元素现在按倒序处理,它会修正一些纠缠错误,但可能会打破一些用户
- 如果您的代码依赖于报告差异的顺序, 那么您的代码将会被打破 。 如果你认为一个对象图是一棵大树,那么
deep-diff执行 对象图的前序倒转然而,当遇到一个阵列时,阵列从一端到一端进行处理,每个元素在再下降时按顺序递归处理.
- 如果您的代码依赖于报告差异的顺序, 那么您的代码将会被打破 。 如果你认为一个对象图是一棵大树,那么
特征
- 获取两个对象之间的结构差异 .
- 观察两个对象之间的结构差异.
- 当结构差异代表变化时,应用从一个对象到另一个对象的改变.
- 当结构差异代表变化时,有选择地将改变从一个对象应用到另一个对象.
安装
npm install @bluelovers/deep-diff
导入
节点
var diff = require('@bluelovers/deep-diff').diff
// or:
// const diff = require('deep-diff');
// const { diff } = require('deep-diff');
// or:
// const DeepDiff = require('deep-diff');
// const { DeepDiff } = require('deep-diff');
// es6+:
// import diff from 'deep-diff';
// import { diff } from 'deep-diff';
// es6+:
// import DeepDiff from 'deep-diff';
// import { DeepDiff } from 'deep-diff';
浏览器
<script src="https://cdn.jsdelivr.net/npm/deep-diff@1/dist/deep-diff.min.js"></script>
在浏览器中,
deep-diff定义全局变量DeepDiff。如果全局命名空间存在冲突,您可以恢复冲突的定义并指定deep-diff变成这样的变量 :var deep = DeepDiff.noConflict();。 。 。 .
简单示例
为了描述差异,变化围绕着 origin 对象。 为保持一致 origin 对象总是在 left-hand-side 行动。 这个 comparand,它可能包含变化,总是在 right-hand-side 行动.
var diff = require('@bluelovers/deep-diff').diff;
var lhs = {
name: 'my object',
description: 'it\'s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'elements']
}
};
var rhs = {
name: 'updated object',
description: 'it\'s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'more', 'elements', { than: 'before' }]
}
};
var differences = diff(lhs, rhs);
五.0.2.0及以上 (单位:千美元) 上面的代码片段将导致描述这些差异的下列结构:
[ { kind: 'E',
path: [ 'name' ],
lhs: 'my object',
rhs: 'updated object' },
{ kind: 'E',
path: [ 'details', 'with', 2 ],
lhs: 'elements',
rhs: 'more' },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 3,
item: { kind: 'N', rhs: 'elements' } },
{ kind: 'A',
path: [ 'details', 'with' ],
index: 4,
item: { kind: 'N', rhs: { than: 'before' } } } ]
差额
差异作为一项或多项变动记录列报。 更改记录的结构如下:
kind- 说明变化类型;将是下列变化之一:N- 表示新增加的财产/要素D- 表明财产/要素被删除E- 表明已编辑财产/内容A- 表示数组内发生的变化
path- 属性路径(从左手边根)lhs- 比较左手边的值( 未定义是否为“ N” 类型)rhs- 比较右侧的值( 未定义是否为 “% ” )index- 当类型 “% 1” 时, 表示变化发生的数组索引item- 当类型“ A” 时, 包含一个嵌入式更改记录, 显示阵列索引上发生的更改
生成所有结构差异的更改记录 origin 财务报告和审定财务报表 comparand。这些方法只考虑对象本身的属性和数组元素;不考虑从对象原型链所继承的元素.
对数组的更改是简单记录的。 我们最关心的是结构的形状;因此我们不花时间来确定一个物体是否从数组中的一个插槽移动到另一个插槽. 相反,我们只记录结构
差别。 如果结构差异是从 comparand 页:1 origin 然后两个对象将比较为“ 深等” , 使用大多数 isEqual 执行,例如载于 摇篮 或者说 下划线。 。 。 .
变动
当两个对象不同时,可以观察到它们被计算时的区别,并有选择地将这些变化应用到原对象(左手侧)上.
var observableDiff = require('deep-diff').observableDiff;
var applyChange = require('deep-diff').applyChange;
var lhs = {
name: 'my object',
description: 'it\'s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'elements']
}
};
var rhs = {
name: 'updated object',
description: 'it\'s an object!',
details: {
it: 'has',
an: 'array',
with: ['a', 'few', 'more', 'elements', { than: 'before' }]
}
};
observableDiff(lhs, rhs, function (d) {
// Apply all changes except to the name property...
if (d.path[d.path.length - 1] !== 'name') {
applyChange(lhs, rhs, d);
}
});
API 文档
标准导入 var diff = require('deep-diff') 在所有代码示例中假设。 导入结果为对象具有下列公共属性:
diff(lhs, rhs[, options, acc])——计算两个对象之间的差异,可选择使用指定的累积器.observableDiff(lhs, rhs, observer[, options])——计算两个对象之间的相差,每个对象向一个观察函数报告.applyDiff(target, source, filter)——将源对象的任何结构差异应用到目标对象上,可选择过滤出每个差异.applyChange(target, source, change)——对目标对象应用单一更改记录. 注:source未使用,可删除.revertChange(target, source, change)将单个更改记录还原为目标对象。 注:source未使用,可删除.
diff
这个 diff 函数计算两个对象之间的相差.
参数
lhs- 左手操作;源对象.rhs- 右手操作;正在从结构上将对象与原对象作比较.options- 可具有下列属性的配置对象:prefilter: 函数,用于决定差异分析是否应在对象图下继续。 此功能还可以取代options后向兼容性参数中的对象.normalize: 预处理的函数 叶子 在树上.
acc- 可选累积器/阵列(要求它具有下列特性:push函数)。 每种差异被推到指定的累积器上.
返回一系列变化,或者,如果没有变化, undefined。这原本是选中的,所以结果将会通过一个真实测试:
var changes = diff(obja, objb);
if (changes) {
// do something with the changes.
}
过滤前对象属性
这个 prefilter'签名应为: function(path, key) 它应该返回任何真实值 path- 说吧key 组合,应当过滤。 如果经过过滤,则差异分析不会在已识别的对象-财产路径上进行进一步分析.
const diff = require('@bluelovers/deep-diff').diff;
const assert = require('assert');
const data = {
issue: 126,
submittedBy: 'abuzarhamza',
title: 'readme.md need some additional example prefilter',
posts: [
{
date: '2018-04-16',
text: `additional example for prefilter for deep-diff would be great.
https://stackoverflow.com/questions/38364639/pre-filter-condition-deep-diff-node-js`
}
]
};
const clone = JSON.parse(JSON.stringify(data));
clone.title = 'README.MD needs additional example illustrating how to prefilter';
clone.disposition = 'completed';
const two = diff(data, clone);
const none = diff(data, clone,
(path, key) => path.length === 0 && ~['title', 'disposition'].indexOf(key)
);
assert.equal(two.length, 2, 'should reflect two differences');
assert.ok(typeof none === 'undefined', 'should reflect no differences');
使对象属性正常化
这个 normalize'签名应为: function(path, key, lhs, rhs) 如果未实现正常化,它应返回病态值,或 [lhs, rhs] 阵列来替换原始值。 如果路径在 prefilter 阶段.
const diff = require('@bluelovers/deep-diff').diff;
const assert = require('assert');
const data = {
pull: 149,
submittedBy: 'saveman71',
};
const clone = JSON.parse(JSON.stringify(data));
clone.issue = 42;
const two = diff(data, clone);
const none = diff(data, clone, {
normalize: (path, key, lhs, rhs) => {
if (lhs === 149) {
lhs = 42;
}
if (rhs === 149) {
rhs = 42;
}
return [lhs, rhs];
}
});
assert.equal(two.length, 1, 'should reflect one difference');
assert.ok(typeof none === 'undefined', 'should reflect no difference');
observableDiff
这个 observableDiff 函数计算两个对象之间的差额,并将每个对象报告给一个观察员函数.
参数
lhs- 左手操作;源对象.rhs- 右手操作;正在从结构上将对象与原对象作比较.observer- 向观察员报告.options- 可具有下列属性的配置对象:prefilter: 函数,用于决定差异分析是否应在对象图下继续。 此功能还可以取代options后向兼容性参数中的对象.normalize: 预处理的函数 叶子 在树上.
捐款
在作出贡献时,铭记着这是一个目标: deep-diff 没有包的依赖性。 这在未来可能有所改变,但目前没有依赖关系.
请在提交公关前进行单位测试: npm test。希望您的PR包含额外的单位测试,以说明您的改变/修改!
当你跑的时候 npm test, 将进行 linting 操作, 任何 linting 错误将失败测试... 这包括代码格式化 .
感谢所有那些贡献至今的人们!