Skip to content

Instantly share code, notes, and snippets.

@digitaldrreamer
Last active October 23, 2024 08:34
Show Gist options
  • Save digitaldrreamer/477a7d0766492d276f899b140bebce3b to your computer and use it in GitHub Desktop.
Save digitaldrreamer/477a7d0766492d276f899b140bebce3b to your computer and use it in GitHub Desktop.
A Function to Compare Two Objects and Get The Difference or return `null`.
/**
* Compares two objects and returns the differences, or null if they're the same
* @param {Object} original - Original form data
* @param {Object} current - Current form data
* @returns {Object|null} Object containing only the changed fields, or null if no changes
*/
function getObjectDiff(original, current) {
const changes = {};
for (const [key, value] of Object.entries(current)) {
// Handle case where original doesn't have the key
if (!(key in original)) {
changes[key] = {
oldValue: undefined,
newValue: value
};
continue;
}
const originalValue = original[key];
const currentValue = value;
if (
originalValue !== currentValue &&
String(originalValue) !== String(currentValue) &&
JSON.stringify(originalValue) !== JSON.stringify(currentValue)
) {
changes[key] = {
old: originalValue,
new: currentValue
};
}
}
// Check for keys that exist in original but not in current
for (const key of Object.keys(original)) {
if (!(key in current)) {
changes[key] = {
old: original[key],
new: undefined
};
}
}
// Return null if no changes were found
return Object.keys(changes).length === 0 ? null : changes;
}
function deepObjectDiff(original, current) {
if (original === current) return null;
// Handle non-object types (including null)
if (
typeof original !== 'object' ||
typeof current !== 'object' ||
original === null ||
current === null
) {
return {
oldValue: original,
newValue: current
};
}
// Handle arrays
if (Array.isArray(original) && Array.isArray(current)) {
if (original.length !== current.length) {
return {
oldValue: original,
newValue: current
};
}
const arrayDiffs = {};
let hasChanges = false;
for (let i = 0; i < original.length; i++) {
const diff = deepObjectDiff(original[i], current[i]);
if (diff !== null) {
arrayDiffs[i] = diff;
hasChanges = true;
}
}
return hasChanges ? arrayDiffs : null;
}
const changes = {};
let hasChanges = false;
// Check for changes in current object
for (const key of Object.keys(current)) {
if (!(key in original)) {
changes[key] = {
oldValue: undefined,
newValue: current[key]
};
hasChanges = true;
continue;
}
const diff = deepObjectDiff(original[key], current[key]);
if (diff !== null) {
changes[key] = diff;
hasChanges = true;
}
}
// Check for deleted keys
for (const key of Object.keys(original)) {
if (!(key in current)) {
changes[key] = {
oldValue: original[key],
newValue: undefined
};
hasChanges = true;
}
}
return hasChanges ? changes : null;
}
export {getObjectDiff, deepObjectDiff};
import { getObjectDiff, deepObjectDiff } from './objectDiff.js';
// Test Cases
console.log("Test 1: Identical objects");
console.log(getObjectDiff(
{ name: "John", age: 30 },
{ name: "John", age: 30 }
));
// Output: null
console.log("Test 2: Different objects");
console.log(getObjectDiff(
{ name: "John", age: 30 },
{ name: "Jane", age: 30 }
));
// Output: { name: { oldValue: "John", newValue: "Jane" } }
console.log("Test 3: Nested objects");
const original = {
name: "John",
age: 30,
address: {
street: "123 Main St",
city: "Boston"
},
hobbies: ["reading", { type: "sports", name: "basketball" }]
};
const current = {
name: "John",
age: 30,
address: {
street: "123 Main St",
city: "New York" // Changed city
},
hobbies: ["reading", { type: "sports", name: "football" }] // Changed sport
};
console.log("Shallow comparison result:", getObjectDiff(original, current));
// const shallowOutput = {
// address: {
// oldValue: {
// street: "123 Main St",
// city: "Boston"
// },
// newValue: {
// street: "123 Main St",
// city: "New York"
// }
// },
// hobbies: {
// oldValue: ["reading", { type: "sports", name: "basketball" }],
// newValue: ["reading", { type: "sports", name: "football" }]
// }
// }
console.log("Deep comparison result:", deepObjectDiff(original, current));
// const deepOutput = {
// address: {
// city: {
// oldValue: "Boston",
// newValue: "New York"
// }
// },
// hobbies: {
// "1": {
// name: {
// oldValue: "basketball",
// newValue: "football"
// }
// }
// }
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment