Skip to content

Instantly share code, notes, and snippets.

@ptb
Created July 18, 2018 09:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ptb/85ef8e240e1a59f710f118894280baf7 to your computer and use it in GitHub Desktop.
Save ptb/85ef8e240e1a59f710f118894280baf7 to your computer and use it in GitHub Desktop.
/* eslint-disable no-use-before-define */
const isArr = Array.isArray
const isMap = (value) => value instanceof Map
const isObj = (value) => typeof value === "object"
const canMerge = (value) =>
Boolean (value) &&
isObj (value) &&
!(/^\[object (?:Date|RegExp)\]$/)
.test (Object.prototype.toString.call (value))
const emptyObj = (value) => (Array.isArray (value) ? [] : new Map ())
const cloneObj = (value) =>
(canMerge (value) ? merge (emptyObj (value), value) : value)
const mergeArr = (target, source) =>
(isArr (target) && isArr (source) ? target.concat (source) : source)
.map (cloneObj)
const mergeMap = (target, source) => {
for (const key of source.keys ()) {
target.set (
key,
merge (target.has (key) && target.get (key), source.get (key))
)
}
return target
}
const objToMap = (value) => new Map (Object.entries (value))
// const mapToObj = (value) =>
// Array.from (value).reduce ((target, [k, v]) => {
// target[k] = v
// return target
// }, {})
const merge = (... sources) =>
sources.reduce ((target, source) => {
if (isArr (source)) {
return mergeArr (target, source)
} else if (canMerge (source)) {
return mergeMap (
isMap (target) ? target : objToMap (target),
isMap (source) ? source : objToMap (source)
)
}
return cloneObj (source)
}, new Map ())
module.exports = merge
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment