I want to be able to get a list of all differences between two JavaScript object graphs, with the property names and values where the deltas occur.
For what it is w
Solution 1
Use JSON.stringify(obj) to get a string representation of the objects you want to compare. Save the string to a file. Use any diff viewer to compare the text files.
Note: JSON.stringify will ignore properties that point to function definitions.
Solution 2
This could do what you want with some modification, it is a modified version of the function _.isEqual (http://documentcloud.github.com/underscore/). Please feel free to suggest any modifications! I wrote it to figure out where the first difference between two objects occur.
// Given two objects find the first key or value not matching, algorithm is a
// inspired by of _.isEqual.
function diffObjects(a, b) {
console.info("---> diffObjects", {"a": a, "b": b});
// Check object identity.
if (a === b) return true;
// Different types?
var atype = typeof(a), btype = typeof(b);
if (atype != btype) {
console.info("Type mismatch:", {"a": a, "b": b});
return false;
};
// Basic equality test (watch out for coercions).
if (a == b) return true;
// One is falsy and the other truthy.
if ((!a && b) || (a && !b)) {
console.info("One is falsy and the other truthy:", {"a": a, "b": b});
return false;
}
// Unwrap any wrapped objects.
if (a._chain) a = a._wrapped;
if (b._chain) b = b._wrapped;
// One of them implements an isEqual()?
if (a.isEqual) return a.isEqual(b);
// Check dates' integer values.
if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
// Both are NaN?
if (_.isNaN(a) && _.isNaN(b)) {
console.info("Both are NaN?:", {"a": a, "b": b});
return false;
}
// Compare regular expressions.
if (_.isRegExp(a) && _.isRegExp(b))
return a.source === b.source &&
a.global === b.global &&
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
// If a is not an object by this point, we can't handle it.
if (atype !== 'object') {
console.info("a is not an object:", {"a": a});
return false;
}
// Check for different array lengths before comparing contents.
if (a.length && (a.length !== b.length)) {
console.info("Arrays are of different length:", {"a": a, "b": b});
return false;
}
// Nothing else worked, deep compare the contents.
var aKeys = _.keys(a), bKeys = _.keys(b);
// Different object sizes?
if (aKeys.length != bKeys.length) {
console.info("Different object sizes:", {"a": a, "b": b});
return false;
}
// Recursive comparison of contents.
for (var key in a) if (!(key in b) || !diffObjects(a[key], b[key])) return false;
return true;
};