Привет Хабр!
Буквально вчера возникла необходимость объединить два объекта javascript. Покопавшись в интернетах узнал, что единственный способ объединить два объекта это скопировать поля из одного в другой.(«Разрывная» — подумал Штирлиц) Пораскинув мозгами создал свой велосипед метод для этого дела.
Основные возможности:
Ну и собственно сама функция:
Всех благодарю за внимание, надеюсь, мойвелосипед метод будет кому-то полезен.
Существует решение этой проблемы с помощью jQuery и функции extend, но не подключать же целый фреймворк ради использования одной функции.
P.S. огромная просьба, если вам не понравилась моя функция напишите в комментариях КОНКРЕТНО, что в ней плохого, с удовольствием поправлю, на хорошее.
Буквально вчера возникла необходимость объединить два объекта javascript. Покопавшись в интернетах узнал, что единственный способ объединить два объекта это скопировать поля из одного в другой.
Основные возможности:
- копирование свойств одного объекта в другой с рекурсивным обходом последнего, на выходе имеем объект, содержащий в себе все свойства первого и второго.
- копирование свойств без рекурсивного обхода объекта-источника, в этом случае на выходе будет объект, сохраняющий исходную структуру первого и второго объекта
- на случай если у двух объектов есть свойства с одинаковым именем предусмотрено два варианта развития событий:
- с сохранением обоих свойств — формируется массив значений
- с заменой исходного целевым
- с сохранением обоих свойств — формируется массив значений
- Ограничение глубины копирования
Ну и собственно сама функция:
/**
*Функция копирования свойств одного объекта в другой
* @param objS <i>object</i> объект из которого будут копироваться свойства
* @param objT <i>&object</i> объект в который будут копироваться свойства
* @param rec <i>bool</i> флаг рекурсивного обхода объекта-источника для полного
* переноса всех свойств иначе поля будут скопированы "как есть"
* @param repl <i>bool</i> флаг замены значений свойств с одинаковым именем
* если он не определен - будет созддан массив значений
* @param max_l_rec <i>int</i> максимальная глубина рекурсии(изменять с осторожностью)
* при значении 1 объекты копируются "как есть"
*/
function objUnion(objS, objT, rec, repl, max_l_rec)
{
//считаем число элементов в исходном объекте
var count_elem = objS.length;
//для контроля рекурсии создадим у целевого объекта два служебных поля,
//первое - глубина рекурсии, второе - количество посчитанных элементов,
//дабы знать, когда достигнут конец копирования и означенные поля можно удалять
if(!objT.hasOwnProperty("cur_l_rec"))
{
objT.cur_l_rec = 0;
objT.summ_elem = 0;
var cur_l_rec = 0;
}
else
{
objT.cur_l_rec++;
cur_l_rec = objT.cur_l_rec;
}
//если достигнут максимальный уровень рекурсии
if(max_l_rec && objT.cur_l_rec == max_l_rec)
{
objUnion(objS, objT, rec, repl, max_l_rec);
delete objT.cur_l_rec ;
return;
}
//начинаем копировать
for(var key in objS)
{
//если текущее поле является объектом
//и определен параметр рекурсивного обхода - заглянем внутрь него
if(typeof(objS[key]) == 'object')
{
if(rec && ((max_l_rec && objT.cur_l_rec < max_l_rec)|| !max_l_rec))
{
objUnion(objS[key], objT, rec, repl, max_l_rec);
objT.cur_l_rec = cur_l_rec;
//если мы вернулись из глубин прибавляем к скопированным элементам единичку
if(objT.cur_l_rec == 0)
{
objT.summ_elem ++;
}
continue;
}
}
//определяем, что делать с полями, имеющими одинаковое имя
//либо создаем из них массив, либо меняем значение первого на второе
if(objT[key] && !repl)
{
objT[key] = [objS[key],objT[key]];
}
else
{
objT[key] = objS[key];
}
}
//если скопированы свой свойства всех объектов убираем служебные поля
if((objT.summ_elem == count_elem || !objS.hasOwnProperty('length')) && (objT.cur_l_rec == 0 && cur_l_rec == 0))
{
delete objT.cur_l_rec ;
delete objT.summ_elem ;
}
}
//небольшой тест
var obj1 = [
{
field4 : {
field9 : {
field10 : 1
}, field8 : 2
},
field5 : 3
},
{
field6 : 5,
field7 : {
field11 : 'green',
field12 : 'black'
}
},
{
field13 : 5,
field14 : {
field15 : 'green',
field16 : 'black'
}
}
];
var obj2 = {
field1 : 'green',
field2 : 'square',
field3 : 'small'
};
//ссылка на объект в который будет копироваться
var link = obj2
objUnion(obj1, link, 1, 0, 1);
//удяляем ссылку
link = null;
console.log(obj2);
Всех благодарю за внимание, надеюсь, мой
Существует решение этой проблемы с помощью jQuery и функции extend, но не подключать же целый фреймворк ради использования одной функции.
P.S. огромная просьба, если вам не понравилась моя функция напишите в комментариях КОНКРЕТНО, что в ней плохого, с удовольствием поправлю, на хорошее.