어제 오늘 내일

[Javascript] 객체 합치는 4가지 방법 (merge) 본문

IT/Javascript

[Javascript] 객체 합치는 4가지 방법 (merge)

hi.anna 2020. 12. 28. 07:11

 

2개 이상의 객체를 합쳐서 하나의 객체로 만드는 방법 4가지를 소개합니다.

  1. 반복문 사용하기
  2. Object.assign()
  3. Spread Operator (전개연산자)
  4. _.merge() (lodash 라이브러리)

 

 

1. 반복문 사용하기

const obj1 = {
  name : 'banana',
  price : 1000
};

const obj2 = {
  name : 'banana',
  price : 2000,
  count : 10
};

// merge object 함수
function mergeObj(obj1, obj2) {
  const newObj = {};
  for (let att in obj1) { 
    newObj[att] = obj1[att]; 
  }

  for(let att in obj2)  {
    newObj[att] = obj2[att];
  }
  
  return newObj;
}

// 결과 출력
document.write(JSON.stringify(mergeObj(obj1, obj2)));

 

 

for...in 루프를 사용하여 객체의 모든 속성값을 읽어서, 새로운 배열로 직접 복사해 주었습니다.

 

 

2. Object.assign()

Object.assign(target, ...sources)

Object.assign() 함수는

파라미터로 입력받은 sources 객체들의 속성을 target 객체로 복사합니다.

이때, sources 객체는 1개이상 여러개 입력 가능합니다.

 

 예제 1  

const obj1 = {
  name : 'banana',
  price : 1000
};

const obj2 = {
  name : 'banana',
  count : 10
};

Object.assign(obj1, obj2);

// 결과 출력
document.write("obj1 : " + JSON.stringify(obj1) + '<br>');
document.write("obj2 : " + JSON.stringify(obj2));

Object.assign(obj1, obj2);

obj2의 모든 속성들을 obj1에 복사합니다.

이때 같은 속성이 있으면 덮어씁니다.

 

출력 결과를 보면 obj1에 obj2의 속성들이 복사된 것을 볼 수 있습니다.

 

 예제 2 

const obj1 = {
  name : 'banana',
  price : 1000
};

const obj2 = {
  name : 'banana',
  count : 10
};

const obj3 = {
  count : 100,
  color : 'yellow'
}

Object.assign(obj1, obj2, obj3);

// 결과 출력
document.write("obj1 : " + JSON.stringify(obj1) + '<br>');
document.write("obj2 : " + JSON.stringify(obj2) + '<br>');
document.write("obj3 : " + JSON.stringify(obj3));

Object.assign(obj1, obj2, obj3);

obj2와 obj3 객체의 속성들을 obj1에 복사합니다.

obj2의 count는 10이고, obj3의 count는 100입니다.

이렇게 source object의 속성이 겹치는 경우, 

Object.assign 함수의 파라미터로 전달된 순서가 뒤인 객체의 값이 복사됩니다.

 

 예제 3 

const obj1 = {
  name : 'banana',
  price : 1000
};

const obj2 = {
  name : 'banana',
  count : 10
};

const newObj = Object.assign({}, obj1, obj2);

// 결과 출력
document.write("newObj : " + JSON.stringify(newObj) + '<br>');
document.write("obj1 : " + JSON.stringify(obj1) + '<br>');
document.write("obj2 : " + JSON.stringify(obj2) + '<br>');

Object.assign() 함수로 객체를 복사하면

Object.assign() 함수의 첫번째 파라미터로 전달된 target 객체가 변경됩니다.

그래서, 예제1과 예제2에서는 target 객체로 전달된 obj1 객체가 변경되었습니다.

 

const newObj = Object.assign({}, obj1, obj2);

obj1과 obj2 객체를 변경하지 않고,

두 객체를 병합하여 새로운 객체를 만들기 위해서

위 예제(예제3)와 같이 target 객체 위치에 빈 객체({})를 전달하였습니다.

그러면, obj1객체와 obj2 객체가 빈 객체({})에 복사되어 병합됩니다.

그리고, 병합된 객체는 Object.assign() 함수의 리턴값으로 리턴됩니다.

위 예제의 출력 결과를 보면

obj1과 obj2는 변경이 되지 않았고,

병합된 결과는 Object.assign()의 리턴값인 newObj에서 확인할 수 있습니다.

 

 

3. Spread Operator (전개연산자)

const obj1 = {
  name : 'banana',
  price : 1000
};

const obj2 = {
  name : 'banana',
  count : 10
};

const newObj = {...obj1, ...obj2}

// 결과 출력
document.write("newObj : " + JSON.stringify(newObj) + '<br>');
document.write("obj1 : " + JSON.stringify(obj1) + '<br>');
document.write("obj2 : " + JSON.stringify(obj2) + '<br>');

 

 

const newObj = {...obj1, ...obj2};

Spread Operator를 사용해서 여러개의 객체를 하나로 병합할 수 있습니다.

Spread Operator는 '...'으로 표시하고, 객체나 배열의 원소를 하나씩 펼쳐서 리턴합니다.

즉, 위 코드는 obj1와 obj2의 각각의 속성들을 하나씩 꺼내어 새로운 객체에 넣어줍니다.

 

 

4. _.merge (lodash 라이브러리)

const obj1 = {
  name : 'Kim',
  tel : ['010-1111-1111', '010-2222-2222'],
};

const obj2 = {
  name : 'Kim',
  address : 'Seoul'
};

const newObj = {...obj1, ...obj2}

// 변경 전 결과 출력
document.write("변경 전" + '<br>');
document.write("newObj : " + JSON.stringify(newObj) + '<br>');

// obj1.tel 배열에 값 추가
obj1.tel.push('010-3333-3333');

// 변경 후 결과 출력
document.write("변경 후" + '<br>');
document.write("newObj : " + JSON.stringify(newObj) + '<br>');

Spread Operator나 Object.assign을 이용해서 객체를 병합하면

Shallow Copy(얕은 복사)가 되면서 두 객체가 합쳐집니다.

Spread Operator나 Object.assign()을 이용하면 위 의 예제와 같이

객체의 속성값이 Object(객체)이거나 Array와 같이 Reference Type일 경우에는

해당 객체의 값이 복사되는게 아니라, 해당 객체를 참조하는 주소값을 복사하면서

두 객체를 병합하게 됩니다.

(Reference Type이 아닌, 문자열이나 숫자 등은 주소값이 아닌 실제값이 복사됩니다.)

실제 값이 복사된 것이 아닌 주소값이 복사되었기 때문에

위 예제에서 obj1.tel의 배열에 새로운 값을 추가했는데도

두 객체의 병합으로 만들어진 newObj의 tel값도 같이 변경된 것을 확인할 수 있습니다.

여기서는 Spread Operator로 예제를 만들었지만, 이것은 Object.assign()의 경우도 마찬가지 입니다.

 

이러한 현상을 피하고, 

실제 값을 복사하고 싶을 때는 lodash 라이브러리의 '_.merge()' 함수를 이용할 수 있습니다. (Deep Copy)

const obj1 = {
  name : 'Kim',
  tel : ['010-1111-1111', '010-2222-2222'],
};

const obj2 = {
  name : 'Kim',
  address : 'Seoul'
};

const newObj = _.merge({}, obj1, obj2)

// 변경 전 결과 출력
document.write("변경 전" + '<br>');
document.write("newObj : " + JSON.stringify(newObj) + '<br>');

// obj1.tel 배열에 값 추가
obj1.tel.push('010-3333-3333');

// 변경 후 결과 출력
document.write("변경 후" + '<br>');
document.write("newObj : " + JSON.stringify(newObj) + '<br>');

const newObj = _.merge({}, obj1, obj2);

lodash의 '_.merge()' 함수는 Object.assign() 함수와 사용법이 비슷합니다.

첫번째 파라미터로는 객체들이 병합될 target 객체를 입력하고,

두번째 파라미터부터는 병합될 source 객체들을 나열합니다.

_.merge() 함수를 이용하여 객체를 병합하니(newObj),

obj1.tel의 배열에 새로운 값을 추가해도,

newObj.tel의 배열값이 변경되지 않는 것을 확인 할 수 있습니다.

 

 

반응형
Comments