Skip to content

Instantly share code, notes, and snippets.

@cferdinandi
Created July 5, 2023 18:08
Show Gist options
  • Save cferdinandi/0272240452e39b9f716923ff9626d9a9 to your computer and use it in GitHub Desktop.
Save cferdinandi/0272240452e39b9f716923ff9626d9a9 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>deepMerge()</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
/**
* Deep merge two or more objects or arrays.
* (c) Chris Ferdinandi, MIT License, https://gomakethings.com
* @param {*} ...objs The arrays or objects to merge
* @returns {*} The merged arrays or objects
*/
function deepMerge (...objs) {
/**
* Get the object type
* @param {*} obj The object
* @return {String} The object type
*/
function getType (obj) {
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
/**
* Deep merge two objects
* @return {Object}
*/
function mergeObj (clone, obj) {
for (let [key, value] of Object.entries(obj)) {
let type = getType(value);
if (clone[key] !== undefined && getType(clone[key]) === type && ['array', 'object'].includes(type)) {
clone[key] = deepMerge(clone[key], value);
} else {
clone[key] = structuredClone(value);
}
}
}
// Create a clone of the first item in the objs array
let clone = structuredClone(objs.shift());
// Loop through each item
for (let obj of objs) {
// Get the object type
let type = getType(obj);
// If the current item isn't the same type as the clone, replace it
if (getType(clone) !== type) {
clone = structuredClone(obj);
continue;
}
// Otherwise, merge
if (type === 'array') {
clone = [...clone, ...structuredClone(obj)];
} else if (type === 'object') {
mergeObj(clone, obj);
} else {
clone = obj;
}
}
return clone;
}
let merlin = {
job: 'Wizard',
spells: ['Dancing teacups', 'Disappear'],
pet: 'owl'
};
let radagast = {
job: 'Druid',
spells: ['Talk to animals', 'Navigate'],
tool: 'staff',
age: 179
};
let mergedWizards = deepMerge(merlin, radagast);
console.log(mergedWizards);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment