Как объединить свойства двух объектов JavaScript?
Я столкнулся с проблемой, когда мне нужно объединить два (очень простых) объекта JavaScript во время выполнения. Например, я хочу сделать следующее:
var obj1 = { food: 'pizza', car: 'ford' }
var obj2 = { animal: 'dog' }
obj1.merge(obj2);
// Теперь у obj1 три свойства: food, car и animal
Существует ли встроенный способ сделать это? Мне не нужна рекурсия, и мне не нужно объединять функции, только методы на плоских объектах.
4 ответ(ов)
Я искал код для слияния свойств объектов и в итоге оказался здесь. Однако, поскольку не нашел готового решения для рекурсивного слияния, написал его сам. (Кстати, метод 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
}
} };
Я сегодня столкнулся с задачей объединения объектов, и ваш вопрос (и ответы на него) очень мне помогли. Я попробовал несколько из предложенных решений, но ни одно из них не удовлетворяло моим требованиям. Поэтому я объединил некоторые идеи, добавил немного своего и разработал новую функцию слияния. Вот она:
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 }));
Если у вас есть свои идеи по улучшению или корректировке этой функции, буду рад их услышать!
Решения, приведенные выше, следует модифицировать, добавив проверку source.hasOwnProperty(property)
в циклах for..in
, прежде чем выполнять присваивание. В противном случае вы рискуете скопировать свойства всей цепочки прототипов, что редко бывает желаемым поведением.
Следующие два метода, вероятно, будут хорошей отправной точкой. Также в lodash есть функция customizer для особых нужд!
_.extend
(http://underscorejs.org/#extend)
_.merge
(https://lodash.com/docs#merge)
Длина объекта в JavaScript
Как проверить, является ли объект массивом?
Как правильно клонировать объект в JavaScript?
Как отобразить объект JavaScript?
Поиск объекта в массиве объектов JavaScript с совпадающим значением