84 lines
2.6 KiB
JavaScript
84 lines
2.6 KiB
JavaScript
'use strict';
|
|
|
|
const isWhat = require('is-what');
|
|
|
|
function concatArrays(originVal, newVal) {
|
|
if (isWhat.isArray(originVal) && isWhat.isArray(newVal)) {
|
|
return originVal.concat(newVal);
|
|
}
|
|
return newVal;
|
|
}
|
|
|
|
function assignProp(carry, key, newVal, originalObject) {
|
|
const propType = {}.propertyIsEnumerable.call(originalObject, key) ? "enumerable" : "nonenumerable";
|
|
if (propType === "enumerable")
|
|
carry[key] = newVal;
|
|
if (propType === "nonenumerable") {
|
|
Object.defineProperty(carry, key, {
|
|
value: newVal,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
});
|
|
}
|
|
}
|
|
function mergeRecursively(origin, newComer, compareFn) {
|
|
if (!isWhat.isPlainObject(newComer))
|
|
return newComer;
|
|
let newObject = {};
|
|
if (isWhat.isPlainObject(origin)) {
|
|
const props2 = Object.getOwnPropertyNames(origin);
|
|
const symbols2 = Object.getOwnPropertySymbols(origin);
|
|
newObject = [...props2, ...symbols2].reduce((carry, key) => {
|
|
const targetVal = origin[key];
|
|
if (!isWhat.isSymbol(key) && !Object.getOwnPropertyNames(newComer).includes(key) || isWhat.isSymbol(key) && !Object.getOwnPropertySymbols(newComer).includes(key)) {
|
|
assignProp(
|
|
carry,
|
|
key,
|
|
targetVal,
|
|
origin
|
|
);
|
|
}
|
|
return carry;
|
|
}, {});
|
|
}
|
|
const props = Object.getOwnPropertyNames(newComer);
|
|
const symbols = Object.getOwnPropertySymbols(newComer);
|
|
const result = [...props, ...symbols].reduce((carry, key) => {
|
|
let newVal = newComer[key];
|
|
const targetVal = isWhat.isPlainObject(origin) ? origin[key] : void 0;
|
|
if (targetVal !== void 0 && isWhat.isPlainObject(newVal)) {
|
|
newVal = mergeRecursively(targetVal, newVal, compareFn);
|
|
}
|
|
const propToAssign = compareFn ? compareFn(targetVal, newVal, key) : newVal;
|
|
assignProp(
|
|
carry,
|
|
key,
|
|
propToAssign,
|
|
newComer
|
|
);
|
|
return carry;
|
|
}, newObject);
|
|
return result;
|
|
}
|
|
function merge(object, ...otherObjects) {
|
|
return otherObjects.reduce((result, newComer) => {
|
|
return mergeRecursively(result, newComer);
|
|
}, object);
|
|
}
|
|
function mergeAndCompare(compareFn, object, ...otherObjects) {
|
|
return otherObjects.reduce((result, newComer) => {
|
|
return mergeRecursively(result, newComer, compareFn);
|
|
}, object);
|
|
}
|
|
function mergeAndConcat(object, ...otherObjects) {
|
|
return otherObjects.reduce((result, newComer) => {
|
|
return mergeRecursively(result, newComer, concatArrays);
|
|
}, object);
|
|
}
|
|
|
|
exports.concatArrays = concatArrays;
|
|
exports.merge = merge;
|
|
exports.mergeAndCompare = mergeAndCompare;
|
|
exports.mergeAndConcat = mergeAndConcat;
|