object/merge.jsjavascript
/**
* 判断值是否可递归合并。
* @private
*/
function isMergeable(value) {
return value !== null && typeof value === 'object' && !ArrayBuffer.isView(value) && !(value instanceof Date) && !(value instanceof RegExp)
}
/**
* 递归合并两个值。
* @private
*/
function mergeValues(target, source) {
if (!isMergeable(source)) return source
const output = Array.isArray(source) ? (Array.isArray(target) ? target.slice() : []) : (isMergeable(target) && !Array.isArray(target) ? { ...target } : {})
Object.entries(source).forEach(([key, value]) => {
output[key] = isMergeable(value) ? mergeValues(output[key], value) : value
})
return output
}
/**
* 深度合并多个普通对象,不修改任何输入对象。
* @function merge
* @memberof module:object
* @param {...Object} objects 要合并的对象
* @returns {Object} 合并后的新对象
* @throws {TypeError} 参数不是普通对象时抛出
*/
function merge(...objects) {
if (objects.some(value => !isMergeable(value) || Array.isArray(value))) throw new TypeError('all arguments must be plain objects')
return objects.reduce((result, object) => mergeValues(result, object), {})
}
export default merge