33

Как объединить свойства двух объектов JavaScript?

16

Я столкнулся с проблемой, когда мне нужно объединить два (очень простых) объекта JavaScript во время выполнения. Например, я хочу сделать следующее:

var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }

obj1.merge(obj2);

// Теперь у obj1 три свойства: food, car и animal

Существует ли встроенный способ сделать это? Мне не нужна рекурсия, и мне не нужно объединять функции, только методы на плоских объектах.

4 ответ(ов)

3

Я искал код для слияния свойств объектов и в итоге оказался здесь. Однако, поскольку не нашел готового решения для рекурсивного слияния, написал его сам. (Кстати, метод jQuery.extend рекурсивный?) Надеюсь, кому-то еще это окажется полезным.

(Код не использует Object.prototype 😃

Код

/*
* Рекурсивно сливает свойства двух объектов 
*/
function MergeRecursive(obj1, obj2) {
  for (var p in obj2) {
    try {
      // Свойство в целевом объекте установлено; обновляем его значение.
      if (obj2[p].constructor == Object) {
        obj1[p] = MergeRecursive(obj1[p], obj2[p]);
      } else {
        obj1[p] = obj2[p];
      }
    } catch (e) {
      // Свойство в целевом объекте не установлено; создаем его и устанавливаем значение.
      obj1[p] = obj2[p];
    }
  }
  return obj1;
}

Пример

o1 = {  a: 1,
        b: 2,
        c: {
          ca: 1,
          cb: 2,
          cc: {
            cca: 100,
            ccb: 200
          }
        } };

o2 = {  a: 10,
        c: {
          ca: 10,
          cb: 20,
          cc: {
            cca: 101,
            ccb: 202
          }
        } };

o3 = MergeRecursive(o1, o2);

В результате мы получаем объект o3 следующего вида:

o3 = {  a: 10,
        b: 2,
        c: {
          ca: 10,
          cb: 20,
          cc: { 
            cca: 101,
            ccb: 202 
          }
        } };
0

Я сегодня столкнулся с задачей объединения объектов, и ваш вопрос (и ответы на него) очень мне помогли. Я попробовал несколько из предложенных решений, но ни одно из них не удовлетворяло моим требованиям. Поэтому я объединил некоторые идеи, добавил немного своего и разработал новую функцию слияния. Вот она:

var merge = function() {
    var obj = {},
        i = 0,
        il = arguments.length,
        key;
    for (; i < il; i++) {
        for (key in arguments[i]) {
            if (arguments[i].hasOwnProperty(key)) {
                obj[key] = arguments[i][key];
            }
        }
    }
    return obj;
};

Вот несколько примеров использования:

var t1 = {
    key1: 1,
    key2: "test",
    key3: [5, 2, 76, 21]
};
var t2 = {
    key1: {
        ik1: "hello",
        ik2: "world",
        ik3: 3
    }
};
var t3 = {
    key2: 3,
    key3: {
        t1: 1,
        t2: 2,
        t3: {
            a1: 1,
            a2: 3,
            a4: [21, 3, 42, "asd"]
        }
    }
};

console.log(merge(t1, t2));
console.log(merge(t1, t3));
console.log(merge(t2, t3));
console.log(merge(t1, t2, t3));
console.log(merge({}, t1, { key1: 1 }));

Если у вас есть свои идеи по улучшению или корректировке этой функции, буду рад их услышать!

0

Решения, приведенные выше, следует модифицировать, добавив проверку source.hasOwnProperty(property) в циклах for..in, прежде чем выполнять присваивание. В противном случае вы рискуете скопировать свойства всей цепочки прототипов, что редко бывает желаемым поведением.

0

Следующие два метода, вероятно, будут хорошей отправной точкой. Также в lodash есть функция customizer для особых нужд!

_.extend (http://underscorejs.org/#extend)

_.merge (https://lodash.com/docs#merge)

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь