# Vanilla JS Diffing Function ## Summary JS only has a few primitives that you should have to worry about for this (so that's nice) but there's not a magic diff-everything function that's native to JavaScript. There are a lot of great libraries that do this which you could pull in if that's a possibility, but it sounds like you need to just use plain old JavaScript to solve this. So, I'll go ahead and break down what you might need to do in that case. ### Divide and Conquer: Write Comparisons by Data Type * String * Number * Array * Object ## Comparison Functions ### Strings ```javascript= // Compare strings and return the difference, char-by-char: const stringDiff = (str1, str2) => { let diff= ''; str2.split('').forEach((char, i) => { if (char != str1.charAt(i)) diff += char ; }); return diff; } ``` ##### Example usage ```javascript= const hash1 = 'f2d17d0102c0edbe21b367f732e8b3d1a549da5e'; const hash2 = 'f6c2a7db18d34b9e971470f8d98ef1652489ec34'; console.log(stringDiff(hash1, hash1)); // Output: '6c2a7db18d34b99714708d98ef165248ec34' // which is the linear difference between strings (rather than // the unique difference between strings). console.log(stringDiff('hello', 'h3llo')); // Output: '3' ``` ### Numbers For numbers, obviously you can just compare their values to see if they match (num1 === num2), or if you want to compute the absolute difference you could write a quick difference function: ```javascript= // Calculate the absolute: const numberDiffAbsolute = (num1, num2) => { return Math.abs(num1 - num2); } // And of course, if you want a value difference you could: num1 - num2 ``` ##### Example Usage ```javascript= const num1 = 120; const num2 = 121; console.log(numberDiffAbsolute(num1, num2)); // Output: 1 ``` ### Arrays With arrays, if you're just looking to compare the two and return the difference – this method should work: ```javascript= const arrayDiff = (arr1, arr2) => arr1.filter(index => !arr2.includes(index)); ``` ##### Example Usage ```javascript= const newArray = [1, 2, 3, 4]; const oldArray = [2, 3]; console.log(arrayDiff(newArray, oldArray)); // Output: [1, 4] ``` ### Objects With objects, checking to see if there's a difference betweent the objects is straightforward. But writing a deep-comparison function may be more time consuming (hence, there are a lot of great libraries out there for this). If you're going to do the latter in Vanilla JS I recommend writing something like [this](https://dmitripavlutin.com/how-to-compare-objects-in-javascript/#4-deep-equality), but instead of returning a boolean to denote equality, push the value differences that you want to track to an array that you can reference (if that's what you need to do). Otherwise, if you just want to check to see if the objects are different you can do a simple shallow equality check like this (not for nested objects): ```javascript= const objectEquality = (obj1, obj2) => { return Object.entries(obj1).toString() === Object.entries(obj2).toString(); } ``` ##### Example Usage ```javascript= const oldObject = {black: 'oh', river: 'when', water: 'will the keys to the kingdom be mine again'}; const newObject = {black: 'oh', river: 'when', water: 'will the keys to the kingdom be mine again'}; console.log(objectEquality(newObject, oldObject)) // Output: true ``` ## Algorithm Split your new comparison function into peices: comparing keys, and comparing values. If you're feeling fancy you can write a class for this, but just writing two functions that reference each other is totally reasonable. ### Comparing Keys Every key will be a string, so using the simple string comparison function I provided should suffice. ### Comparing Values You'll probably want to write a function that does something like this: * Parameters: `new value`, `old value` * Error check: return an error if the data types of the values are different, etc. * Switch statement: call comparison functions based on the data type of the new value. * Case `string`: run `stringDiff` ```javascript= // Number check: typeof newValue === 'string'; ``` * Case `number`: run `numberDiffAbsolute` ```javascript= // Number check: typeof newValue === 'number'; ``` * Case `array`: run `arrayDiff` ```javascript= // Array check: Array.isArray(newValue); ``` * Case `object`: run `objectEquality`, or a `deepObjectDiff` function like I described there. ```javascript= // There is no 'isObject' function in JS, so you'll have to write your own: const isObject = (obj) => { return Object.prototype.toString.call(obj) === '[object Object]'; }; // It's important to use something you can be sure of like this, because this is // JavaScript you know, so if you run something like: typeof myArray // The output will be: 'object' – not what you want. ```