Last active
December 30, 2022 05:37
-
-
Save markgarrigan/d8704fb8cf179fd2c31ede66e1e0b028 to your computer and use it in GitHub Desktop.
Deep diff of javascript object.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Not really needed. Just used for logging the FULL diff in the console | |
const util = require('util') | |
// Set up the diffs object | |
let diffs | |
function compare(item1, item2, diffRef = diffs, key) { | |
// Make sure we have a key | |
if (!key && key !== 0) { | |
return | |
} | |
// Get the types of things we're comparing | |
const type1 = Object.prototype.toString.call(item1) | |
const type2 = Object.prototype.toString.call(item2) | |
const diffType = Object.prototype.toString.call(diffRef) | |
// The item does not exist in the second object | |
// Remove it from an array | |
// Set it to null in an object | |
if (type2 === '[object Undefined]') { | |
if (diffType === '[object Array]') { | |
return | |
} | |
diffRef[key] = null | |
return | |
} | |
// The types are different just replace the whole item | |
if (type1 !== type2) { | |
diffRef[key] = item2 | |
return | |
} | |
// The type is a function and they are different just replace the whole item | |
if (type1 === '[object Function]') { | |
if (item1.toString() !== item2.toString()) { | |
diffRef[key] = item2 | |
return | |
} | |
} | |
// Convert the items to strings | |
string1 = JSON.stringify(item1) | |
string2 = JSON.stringify(item2) | |
// The strings are the same | |
// If were working with an array add the item to the array | |
// Everything else do nothing | |
if (string1 === string2) { | |
if (diffType === '[object Array]') { | |
diffRef[key] = item2 | |
} | |
return | |
} | |
// The item is an object | |
// We need to dig deeper | |
if (type1 === '[object Object]') { | |
diffRef[key] = diffRef[key] || {} | |
deepDiff(item1, item2, diffRef[key]) | |
return | |
} | |
// The item is an array | |
// We need to dig deeper | |
if (type1 === '[object Array]') { | |
item1.forEach((deepItem1, index) => { | |
const deepItem2 = item2[index] | |
diffRef[key] = diffRef[key] || [] | |
compare(deepItem1, deepItem2, diffRef[key], index) | |
}) | |
return | |
} | |
// The item is a string, number, boolean, etc | |
// Just compare them | |
if (item1 != item2) { | |
diffRef[key] = item2 | |
return | |
} | |
} | |
function deepDiff(thing1, thing2, diffRef) { | |
diffs = !diffRef ? {} : diffs | |
// Loop through the first object | |
for (key in thing1) { | |
if (thing1[key]) { | |
compare(thing1[key], thing2[key], diffRef, key) | |
} | |
} | |
// Loop through the second object and find missing items | |
for (key in thing2) { | |
if (thing2[key]) { | |
compare(thing1[key], thing2[key], diffRef, key) | |
} | |
} | |
return diffs | |
} | |
// Test data | |
const thing1 = { | |
id: 1, | |
name: 'Mark', | |
birthday: '01/01/1990', | |
address: { | |
street: '123 Main St', | |
city: 'New York', | |
state: 'NY', | |
zip: '12345', | |
garbage: { | |
monday: false, | |
wednesday: true, | |
friday: { | |
morning: true, | |
afternoon: true | |
} | |
} | |
}, | |
cars: ['Honda', 'BMW', { make: 'Chevy', model: 'Blazer' }, 'Ford'], | |
init: () => { | |
console.log('hello') | |
} | |
} | |
// Test data | |
const thing2 = { | |
id: '2', | |
name: 'Mark', | |
age: 30, | |
address: { | |
street: '123 Main St', | |
city: 'New York', | |
state: 'WI', | |
zip: '12345', | |
garbage: { | |
monday: true, | |
wednesday: true, | |
friday: { | |
morning: true, | |
afternoon: false | |
}, | |
saturday: true | |
} | |
}, | |
cars: ['Ford', 'BMW', { make: 'Chevy', model: 'Camaro', year: '1988' }], | |
init: () => { | |
console.log('hellos') | |
} | |
} | |
const t0 = performance.now() | |
deepDiff(thing1, thing2) | |
const t1 = performance.now() | |
console.log(`Getting the difference took ${t1 - t0} milliseconds.`) | |
console.log('Here are your differences.', util.inspect(diffs, false, null, true /* enable colors */)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment