_baseMergeDeep.js 2.6 KB

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