Skip to content

Instantly share code, notes, and snippets.

@markgarrigan
Last active December 30, 2022 05:37
Show Gist options
  • Save markgarrigan/d8704fb8cf179fd2c31ede66e1e0b028 to your computer and use it in GitHub Desktop.
Save markgarrigan/d8704fb8cf179fd2c31ede66e1e0b028 to your computer and use it in GitHub Desktop.
Deep diff of javascript object.
// 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