Here you go:
http://jsfiddle.net/musicin3d/cf5ddod1/3/
Edited down version for your no-clicking pleasure:
// Call this function.
// The others are helpers for this one.
function getDiff(a, b){
var diff = (isArray(a) ? [] : {});
recursiveDiff(a, b, diff);
return diff;
}
function recursiveDiff(a, b, node){
var checked = [];
for(var prop in a){
if(typeof b[prop] == 'undefined'){
addNode(prop, '[[removed]]', node);
}
else if(JSON.stringify(a[prop]) != JSON.stringify(b[prop])){
// if value
if(typeof b[prop] != 'object' || b[prop] == null){
addNode(prop, b[prop], node);
}
else {
// if array
if(isArray(b[prop])){
addNode(prop, [], node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
// if object
else {
addNode(prop, {}, node);
recursiveDiff(a[prop], b[prop], node[prop]);
}
}
}
}
}
function addNode(prop, value, parent){
parent[prop] = value;
}
function isArray(obj){
return (Object.prototype.toString.call(obj) === '[object Array]');
}
See the link above for more details. There is a comment that explains some of my assumptions.
This is an example of how to use recursion to solve your problem. If you're not familiar with recursion, I suggest you do some reading. Here's a SO article about it:
What is recursion and when should I use it?
Of note:
Using JSON.stringify
like I did is not a good idea. It's convenient for me as the programmer because my program can "look ahead" to see if there's a change down each path, but that comes at a cost. I'm already traversing the tree structure to do my work, and JSON.stringify
also traverses the tree structure of every object I send every time I call it. In computer science we call this a worst case scenario of O(n!), less formally referred to as "very slow." A better design would just traverse the entire tree and keep track of how it got to where it was. When it came to a dead end (called a "leaf" node"), it would use this knowledge to add the necessary data structure to the diff
variable all at once. This would mean our program would have to traverse the entire data structure, but our code would be the only thing doing it. So each node would be processed only once.
Still, this should give you an idea of what others were suggesting.