JavaScript / Объединение объектов

в 7:54, , рубрики: javascript, object, метки: ,

Привет!
Буквально вчера возникла необходимость объединить два объекта javascript. Каково же было мое удивление, когда оператор + вместо ожидаемого слияния объектов вернул мне строку… Покопавшись в интернетах узнал, что единственный способ объединить два объекта это скопировать поля из одного в другой. («Разрывная» — подумал Штирлиц) Пораскинув мозгами создал свой велосипед метод для этого дела.

Основные возможности:

  1. копирование свойств одного объекта в другой с рекурсивным обходом последнего, на выходе имеем объект, содержащий в себе все свойства первого и второго.
  2. копирование свойств без рекурсивного обхода объекта-источника, в этом случае на выходе будет объект, сохраняющий исходную структуру первого и второго объекта
  3. на случай если у двух объектов есть свойства с одинаковым именем предусмотрено два варианта развития событий:
    1. с сохранением обоих свойств — формируется массив значений
    2. с заменой исходного целевым

  4. Ограничение глубины копирования

Ну и собственно сама функция:

  /**  	*Функция копирования свойств одного объекта в другой  	* @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> максимальная глубина рекурсии(изменять с осторожностью)  	* @param cur_l_rec <i>int</i> текущая глубина рекурсии(не изменять)  	*/  function objUnion(objS, objT, rec, repl, max_l_rec, cur_l_rec)  {  	//считаем число элементов в исходном объекте  	var count_elem = objS.length;  	//если мы вернулись из глубин прибавляем к скопированным элементам единичку  	if(cur_l_rec == 0)  	{  		objT.summ_elem ++;  	}  	//для контроля рекурсии создадим у целевого объекта два служебных поля,  	//первое - глубина рекурсии, второе - количество посчитанных элементов,  	//дабы знать, когда достигнут конец копирования и означенные поля можно удалять  	if(typeof(objT.cur_l_rec) == 'undefined')  	{  		objT.cur_l_rec = 0;  		objT.summ_elem = 0;    		cur_l_rec = 0;  	}  	else  	{  		objT.cur_l_rec++;  		cur_l_rec++;  	}    	//если достигнут максимальный уровень рекурсии  	if(max_l_rec && objT.cur_l_rec == max_l_rec)  	{  		objUnion(objS, objT, rec, repl, max_l_rec, cur_l_rec);  		delete objT.cur_l_rec ;  		return;  	}  	var flag_rec = false;  	//начинаем копировать  	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))  			{  				flag_rec = true;  				objUnion(objS[key], objT, rec, repl, max_l_rec, cur_l_rec);  				continue;  			}  		}  		//определяем, что делать с полями, имеющими одинаковое имя  		//либо создаем из них массив, либо меняем значение первого на второе  		if(objT[key] && !repl)  		{  			objT[key] = [objS[key],objT[key]];  		}  		else  		{  			objT[key] = objS[key];  		}  	}  	//если скопированы свой свойства всех объектов убираем служебные поля  	if((objT.summ_elem == count_elem && cur_l_rec == 0) || !flag_rec)  	{  		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, 0);  //удяляем ссылку  link = null;  console.log(obj2);  

Всех благодарю за внимание, надеюсь, мой велосипед метод будет кому-то полезен.

Автор: Slavenin999

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js