_baseMergeDeep.js (3069B)
1 var assignMergeValue = require('./_assignMergeValue'), 2 cloneBuffer = require('./_cloneBuffer'), 3 cloneTypedArray = require('./_cloneTypedArray'), 4 copyArray = require('./_copyArray'), 5 initCloneObject = require('./_initCloneObject'), 6 isArguments = require('./isArguments'), 7 isArray = require('./isArray'), 8 isArrayLikeObject = require('./isArrayLikeObject'), 9 isBuffer = require('./isBuffer'), 10 isFunction = require('./isFunction'), 11 isObject = require('./isObject'), 12 isPlainObject = require('./isPlainObject'), 13 isTypedArray = require('./isTypedArray'), 14 safeGet = require('./_safeGet'), 15 toPlainObject = require('./toPlainObject'); 16 17 /** 18 * A specialized version of `baseMerge` for arrays and objects which performs 19 * deep merges and tracks traversed objects enabling objects with circular 20 * references to be merged. 21 * 22 * @private 23 * @param {Object} object The destination object. 24 * @param {Object} source The source object. 25 * @param {string} key The key of the value to merge. 26 * @param {number} srcIndex The index of `source`. 27 * @param {Function} mergeFunc The function to merge values. 28 * @param {Function} [customizer] The function to customize assigned values. 29 * @param {Object} [stack] Tracks traversed source values and their merged 30 * counterparts. 31 */ 32 function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { 33 var objValue = safeGet(object, key), 34 srcValue = safeGet(source, key), 35 stacked = stack.get(srcValue); 36 37 if (stacked) { 38 assignMergeValue(object, key, stacked); 39 return; 40 } 41 var newValue = customizer 42 ? customizer(objValue, srcValue, (key + ''), object, source, stack) 43 : undefined; 44 45 var isCommon = newValue === undefined; 46 47 if (isCommon) { 48 var isArr = isArray(srcValue), 49 isBuff = !isArr && isBuffer(srcValue), 50 isTyped = !isArr && !isBuff && isTypedArray(srcValue); 51 52 newValue = srcValue; 53 if (isArr || isBuff || isTyped) { 54 if (isArray(objValue)) { 55 newValue = objValue; 56 } 57 else if (isArrayLikeObject(objValue)) { 58 newValue = copyArray(objValue); 59 } 60 else if (isBuff) { 61 isCommon = false; 62 newValue = cloneBuffer(srcValue, true); 63 } 64 else if (isTyped) { 65 isCommon = false; 66 newValue = cloneTypedArray(srcValue, true); 67 } 68 else { 69 newValue = []; 70 } 71 } 72 else if (isPlainObject(srcValue) || isArguments(srcValue)) { 73 newValue = objValue; 74 if (isArguments(objValue)) { 75 newValue = toPlainObject(objValue); 76 } 77 else if (!isObject(objValue) || isFunction(objValue)) { 78 newValue = initCloneObject(srcValue); 79 } 80 } 81 else { 82 isCommon = false; 83 } 84 } 85 if (isCommon) { 86 // Recursively merge objects and arrays (susceptible to call stack limits). 87 stack.set(srcValue, newValue); 88 mergeFunc(newValue, srcValue, srcIndex, customizer, stack); 89 stack['delete'](srcValue); 90 } 91 assignMergeValue(object, key, newValue); 92 } 93 94 module.exports = baseMergeDeep;