Привет Хабр!
Буквально вчера возникла необходимость объединить два объекта 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. огромная просьба, если вам не понравилась моя функция напишите в комментариях КОНКРЕТНО, что в ней плохого, с удовольствием поправлю, на хорошее.