merge-deep.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. /**
  2. * Глубокое объединение двух объектов.
  3. *
  4. * Если оба значения массивы, то выполняется объединение.
  5. * Если оба значения объекты, то выполняется объединение.
  6. * В остальных случаях значение из source перезаписывает target.
  7. *
  8. * @param {*} target
  9. * @param {*} source
  10. * @returns {*}
  11. */
  12. export function mergeDeep(target, source) {
  13. const isObject = item => {
  14. return item && typeof item === 'object' && !Array.isArray(item);
  15. };
  16. // если оба значения массивы, то возвращается
  17. // новый массив с их объединением
  18. if (Array.isArray(target) && Array.isArray(source)) {
  19. return [...target, ...source];
  20. }
  21. // если оба значения объекты,
  22. // то выполняется глубокое слияние
  23. if (isObject(target) && isObject(source)) {
  24. // создание поверхностной копии первого объекта
  25. const result = {...target};
  26. // обход ключей второго объекта
  27. Object.keys(source).forEach(key => {
  28. const targetValue = target[key];
  29. const sourceValue = source[key];
  30. // если ключ есть и в первом объекте,
  31. // то выполняется объединение их значений
  32. if (Object.prototype.hasOwnProperty.call(target, key)) {
  33. result[key] = mergeDeep(targetValue, sourceValue);
  34. } else {
  35. // если ключа нет в первом объекте,
  36. // то берется значение из второго
  37. result[key] = sourceValue;
  38. }
  39. });
  40. return result;
  41. }
  42. // во всех остальных случаях значение
  43. // из source перезаписывает target
  44. return source;
  45. }