Skip to content

Instantly share code, notes, and snippets.

@black-black-cat
Created December 5, 2019 16:14
Show Gist options
  • Save black-black-cat/a896fbf7dd24307705de5e17ad3523a6 to your computer and use it in GitHub Desktop.
Save black-black-cat/a896fbf7dd24307705de5e17ad3523a6 to your computer and use it in GitHub Desktop.
deep merge deepMerge
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>GistRun</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1>Hello world!</h1>
<script src="script.js"></script>
</body>
</html>
function isType (v, type) {
return ({}).toString.call(v) === '[object Array]'
? 'array'
: ({}).toString.call(v) === '[object Object]'
? 'object'
: 'others'
}
function isMergeable (v) {
let type = isType(v)
return type === 'array' || type === 'object'
}
function deepMerge (target, source) {
let isSourceArray = isType(source) === 'array'
let isTargetArray = isType(target) === 'array'
let isTypesMatch = isSourceArray === isTargetArray
if (!isTypesMatch) {
return clone(source)
} else if (isSourceArray) {
return mergeArray(target, source)
} else {
return mergeObject(target, source)
}
}
function empty(v) {
return isType(v) === 'array' ? [] : {}
}
function clone (v) {
return isMergeable(v) ? deepMerge(empty(v), v) : v
}
function mergeObject(target, source) {
let dist = {}
if (isMergeable(target)) {
Object.keys(target).forEach(key => {
dist[key] = clone(target[key])
})
}
Object.keys(source).forEach(key => {
if (dist[key] && isMergeable(source[key])) {
dist[key] = deepMerge(dist[key], source[key])
} else {
dist[key] = clone(source[key])
}
})
return dist
}
function mergeArray(target, source) {
return [...target, ...source].map((item) => {
return clone(item)
})
}
deepMerge.all = function deepMergeAll (arr = []) {
return arr.reduce((memo, item) => {
return deepMerge(memo, item)
}, empty(arr[0]))
}
const x = {
foo: { bar: {b: 12} },
array: [{
does: 'work',
too: [ 1, 2, 3 ]
}]
}
const y = {
foo: { baz: 4 },
quux: 5,
array: [{
does: 'work',
too: [ 4, 5, 6 ]
}, {
really: 'yes'
}]
}
const z = {
foo: { bar: {a: 33}}
}
const d = {
foo: { bar: {a: 9, d: 13, b: 1}}
}
console.log(deepMerge.all([x, y, z, d]))
/* todo: add styles */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment