Skip to content

Instantly share code, notes, and snippets.

@dhenson02
Last active June 12, 2016 23:04
Show Gist options
  • Save dhenson02/85e93a9d7ab51e7237d461fd8c0df301 to your computer and use it in GitHub Desktop.
Save dhenson02/85e93a9d7ab51e7237d461fd8c0df301 to your computer and use it in GitHub Desktop.
/**
* Custom deep diffing to tell what changes throughout our data transfers
* Don't recommend for testing functions or recursively-nested objects (like Backbone collections).
* @param item1 <>
* @param item2 <>
* @param [isReversed] <Boolean>
* @returns <Array>(Object*)
*/
function deepDiff ( item1, item2, isReversed ) {
function isEmpty ( val ) {
return typeof val === 'undefined' || val === null || Number.isNaN(val);
}
function makeFail ( val1, val2, key ) {
return {
key: key,
val1: !isReversed ? val1 : val2,
val2: !isReversed ? val2 : val1
};
}
function propDiff ( first, second, key ) {
if ( isEmpty(first) || isEmpty(second) ) {
return [ makeFail(first, second, key) ]
}
var firstKeys = Object.keys(first);
var secondKeys = Object.keys(second);
var needsReverse = firstKeys.length !== secondKeys.length;
var fails = Object.keys(first).reduce(function ( fails, key ) {
// console.log(key, first[ key ], second[ key ]);
if ( first[ key ] === second[ key ] ) {
return fails;
}
if ( !second.hasOwnProperty(key) ) {
needsReverse = true;
fails.push(makeFail(first[ key ], '***MISSING***', key));
}
else {
return fails.concat(compareValues(first[ key ], second[ key ], key));
}
return fails;
}, []);
if ( needsReverse === true && isReversed !== true ) {
return fails.concat(deepDiff(second, first, true));
}
return fails;
}
function testArrays ( val1, val2, key, isReversed ) {
var shouldContinue = function ( val1, val2 ) {
return typeof val1 === typeof val2 && (
typeof val1 !== 'string' ||
typeof val1 !== 'number' ||
typeof val1 !== 'boolean' );
};
var needsReverse = val1.length !== val2.length;
var fails = val1.reduce(function ( missing, value, index ) {
var newKey = key !== null ?
( key + '[' + index + ']' ) :
index;
if ( val2.indexOf(value) === -1 ) {
if ( shouldContinue(value, val2[ index ]) ) {
return missing.concat(deepDiff(value, val2[ index ], newKey));
}
else {
needsReverse = true;
missing.push(makeFail(value, '***MISSING***', newKey));
}
}
return missing;
}, []);
if ( needsReverse === true && isReversed !== true ) {
return fails.concat(testArrays(val2, val1, key, true));
}
return fails;
}
function compareValues ( val1, val2, key ) {
var fails = [];
if ( typeof val1 === 'object' ) {
if ( typeof val2 === 'object' ) {
if ( Array.isArray(val1) ) {
if ( Array.isArray(val2) ) {
return fails.concat(testArrays(val1, val2, key));
}
else {
fails.push(makeFail(val1, val2, key));
}
}
else {
return fails.concat(propDiff(val1, val2, key));
}
}
else {
fails.push(makeFail(val1, val2, key));
}
}
else {
fails.push(makeFail(val1, val2, key));
}
return fails;
}
function diff ( first, second ) {
return first !== second ? compareValues(first, second, null) : [];
}
if ( typeof item2 === 'undefined' ) {
return function ( item2 ) {
return diff(item1, item2);
}
}
return diff(item1, item2);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment