比较两个JSON对象以查看角度变化
Compare Two JSON Objects to See Changes Angular
我需要重构我的程序,以获取一个JSON对象,将其存储在某个地方,进行一系列更改,然后比较这两个对象,查看更改、删除和添加了什么。
我不确定在JS中有什么方法可以做到这一点,所以有人能在Angular(对象比较部分)中建议一种方法吗?否则,我将不得不对我的程序运行方式进行大量更改/从后端尝试。感谢您的帮助。
对象比较的唯一内置操作是==
/===
相等运算符,它使用引用相等:A是B,而不是A等于B。
您想要的是一个描述两个对象之间差异的更改描述符列表。
正如注释中所指出的,这将需要对对象进行递归遍历,同时使用引用和存在性检查。
下面的算法是一个想法的快速实现。将遍历这些对象,并使用对象列表描述它们的更改。就像对象本身一样,更改是嵌套的,但根据它们在对象中的位置有一个唯一的id(因此可以将其展平)。
function diff(a, b, namespace) {
namespace = (namespace || '') + '.';
var keysInA = Object.keys(a),
keysInB = Object.keys(b);
var diffA = keysInA.reduce(function(changes, key) {
var ns = namespace + key;
if(typeof b[key] == 'undefined') {
return changes.concat([{ type: 'DELETED', id: ns }]);
}
if(a[key] !== b[key]) {
return changes.concat([{ type: 'CHANGED', id: ns }]);
}
if(typeof a[key] == b[key] == 'object') {
return diff(a[key], b[key], ns);
}
return changes;
}, []);
var diffB = keysInB.reduce(function(changes, key) {
var ns = namespace + key;
if(typeof a[key] == 'undefined') {
return changes.concat([{ type: 'ADDED', id: ns }]);
}
return changes;
}, []);
return diffA.concat(diffB);
}
例如,我们取一个对象的原始状态。
var a = { a: 1, b: 2, c: 3 };
还有新的州。
var b = { a: 2, c: 3, d: 5 };
然后使用diff
函数运行它们。
diff(a, b);
它返回一个更改列表。
[
{ id: '.a', type: 'CHANGED' },
{ id: '.b', type: 'DELETED' },
{ id: '.d', type: 'ADDED' }
]
显然,您必须调整此算法,使其符合您的变更标准。你可能想看看深层次的平等,而不是一直比较引用。
我将在这里添加Dan建议的实现,以防它能帮助那些想要看到实际实现的人:
var propertiesToIgnore = ['.indexesTracked', '.notInSyncWithDb', '.date', '.details.updatedAt', '.autoLoadLocalStorage', '.deletionQueue']; //these are extraneous properties added to project that should not be represented in interface (and not tracked)
var keysToIgnore = ['addAllDatacuts', 'datacutNames']; // this just looks at the property rather than the above which matches from the project root
function diff(a, b, namespace, firstCall) {
namespace = firstCall ? (namespace || '') : (namespace || '') + '.';
var keysInA = Object.keys(a),
keysInB = Object.keys(b);
var diffA = keysInA.reduce(function(changes, key) {
var ns = namespace + key;
if (propertiesToIgnore.indexOf(ns) !== -1 || keysToIgnore.indexOf(key) !== -1) {
return changes;
}
if (key == '$$hashKey') {
return changes;
}
if (angular.equals(a[key], b[key])) { // whole chain is equal so I do not need to iterate over this branch
return changes;
}
if (typeof b[key] == 'undefined') {
return changes.concat([{ type: 'DELETED', id: ns }]);
}
if (a[key] !== b[key] && (typeof b[key] !== 'object' || typeof a[key] !== 'object')) {
return changes.concat([{ type: 'UPDATED', id: ns }]);
}
if (typeof b[key] === 'object' && typeof a[key] === 'object') {
return changes.concat(diff(a[key], b[key], ns));
}
if (a[key] === null || b[key] === null) { // avoids values that are null as js considers null an object
return changes;
}
if(typeof a[key] == 'object' && typeof b[key] == 'object' && typeof a[key].getMonth !== 'function' && typeof b[key].getMonth !== 'function') { // last part necessary to make sure it is not a date object
return diff(a[key], b[key], ns);
}
return changes;
}, []);
var diffB = keysInB.reduce(function(changes, key) {
var ns = namespace + key;
if (propertiesToIgnore.indexOf(ns) !== -1 || keysToIgnore.indexOf(key) !== -1) {
return changes;
}
if (key == '$$hashKey') {
return changes;
}
if (typeof a[key] == 'undefined') {
return changes.concat([{ type: 'ADDED', id: ns }]);
}
return changes;
}, []);
return diffA.concat(diffB);
}
$scope.changes = diff(dbData, $scope.project, '');
相关文章:
- Javascript对象颜色动态变化
- Knockoutjs当父对象's可观察到的变化
- 在异步函数调用过程中,当对象的属性值发生变化时,JavaScript中的对象属性值会发生什么变化
- Javascript单元测试依赖关系-当依赖对象发生变化时,如何使测试失败
- AngularJS:如何在指令范围的对象发生变化时更新与控制器作用域相关联的控制器作用域
- 比较两个JSON对象以查看角度变化
- 计算JavaScript对象中属性百分比的变化
- Angular:当列表发生变化时,如何重新绑定到之前选择的对象
- 检测JS中CSSStyleDeclaration对象的变化
- 升级到jQuery 1.7和事件对象的变化
- Rxjs观察对象的更新和变化
- 为什么JavaScript参数对象会因赋值给参数而发生变化?
- addEventListener的变化,可以访问一个对象中的方法
- 为什么在调用对对象方法的引用时,方法的“this”会发生变化
- JavaScript修改对象原型来监控变化
- 继承对象的变化反映到父对象
- 如何观察对象方法返回的属性变化
- 可以'我不明白为什么我的对象中的值在变化
- 如果克隆的对象发生变化,则重新克隆对象
- 如何在服务中观察数组或对象的变化