javascript object merge

Object.assign

Javascript의 Object를 Merge 하는 방법 중에 가장 많이 사용되는 것은 Object.assign을 사용하는 것이다.

기본 사용법은 다음과 같다.

Object.assign(target, ...sources)

  • target : Merge 당할 대상 객체
  • source : Merge의 대상 객체에게 주입을 할 오브젝트
기본 사용법
var obj1 = {name : 'hi', val: 1};
var obj2 = {name : 'hello', val: 2};

var newObj = Object.assign(obj1, obj2);

console.log(obj1);
console.log(newObj);

obj1.name = 'modified';

console.log(obj1);

if (obj1 === newObj){
console.log('same object!!')
}

실행 결과

{ name: 'hello', val: 2 }
{ name: 'hello', val: 2 }
{ name: 'modified', val: 2 }
same object!!

여기서 주목해야할 점은 target의 object는 assign 이후 자기 자신의 original 영역을 지속적으로 참조 하고 있다는 것이다.

  • 즉, obj1과 newobj는 완전히 동일한 object라는 것이다.

target이었던 obj1의 값은

var newObj = Object.assign(obj1, obj2);

이후 obj2의 값으로 덮어 쒸워 지는 것을 볼 수 있다.

  • target의 object는 source object와 동일한 properties가 있다면 overwrite 되게 된다.

코드를 아래와 같이 살짝 변경해 보겠다.

var obj1 = {pre:'King', name : 'hi', val: 1};
var obj2 = {name : 'hello', val: 2, nextVal :3};

var newObj = Object.assign(obj1, obj2);

console.log(obj1);
console.log(newObj);

obj1.name = 'modified';

console.log(obj1);

if (obj1 === newObj){
console.log('same object!!')
}

변경 점은 source에 pre property가 생겼고, obj2에는 nextVal을 생성 했다. 해당 코드를 실행해 보면 아래와 같은 결과 값을 확인 할 수 있다.

{ pre: 'King', name: 'hello', val: 2, nextVal: 3 }
{ pre: 'King', name: 'hello', val: 2, nextVal: 3 }
{ pre: 'King', name: 'modified', val: 2, nextVal: 3 }
same object!!

상위 결과에서 볼 수 있듯이

  • 해당 메서드는 서로에게 갖지 않는 값에 대해서는 target으로 값이 주입된다.
Cloning

이러한 방법을 이용해서 객체에 대한 내부 properties Cloning이 가능하다.

var obj1 = {pre:'King', name : 'hi', val: 1};

var clonedObj = Object.assign({}, obj1);

console.log(obj1);
console.log(clonedObj);

obj1.name = 'modified';

console.log(obj1);

if (obj1 === clonedObj){
console.log('same object!!');
} else {
console.log('different object!!');
}

결과 값은 다음과 같다.

{ pre: 'King', name: 'hi', val: 1 }
{ pre: 'King', name: 'hi', val: 1 }
{ pre: 'King', name: 'modified', val: 1 }
different object!!

객체에 대한 정보를 동일하게 copy 하였으나,

  • 기존 object와는 다른 object를 생성한 것을 확인 가능하다.

ES6 Spread Operator

ES6 문법에서 사용되는 spread operator를 이용해서 merge가 가능하다.

기본 사용법
var obj1 = [1,2,3];
var obj2 = [4,5,6];

var length = obj1.push(...obj2);

console.log(length);
console.log(obj1);
obj1.push(7);
console.log(obj2);

if (obj1 === obj2){
console.log('same object!!');
} else {
console.log('different object!!');
}

결과값은 다음과 같다.

6
[ 1, 2, 3, 4, 5, 6 ]
[ 4, 5, 6 ]
different object!!

본 사용법은 사실 object간의 결합을 대상으로 하지 않는다. spread operator 자체가 array와 같은 Iterator성 객체를 대상으로한 문법이기 때문이다.

  • 결과적으로 Array의 결합으로 볼수 있으나 object의 merge용도로 사용되지는 않는다.

이런식의 코드도 많이 사용할 수 있다.

> var obj1 = [1,2,3];
> var obj2 = [...obj1, 4,5,6];
>
> console.log(obj2);
> [ 1, 2, 3, 4, 5, 6 ]

ECMAScript 2018 기준으로는 다음 코드도 사용이 가능하다.

> var obj1 = {test:1};
> var obj2 = {test:2,after:3};
>
> var merged = {...obj1, ...obj2};
> console.log(obj1);

그러나 아직 널리 사용 되지 않음으로 더 다루지 않는다.

Undersocre Extend

언더스코어 라이브러리를 사용해서 객체 머지가 가능하다.

기본 사용법
const _ = require('underscore');

var obj1 = {a:1,b:2};
var obj2 = {c:3,d:4};
var obj3 = {c:3,d:5,e:6};

_.extend(obj1, obj2, obj3);

console.log(obj1);

if (obj1 === obj2) {
console.log('same Object');
} else {
console.log('different Object');
}

결과는 다음과 같다.

{ a: 1, b: 2, c: 3, d: 5, e: 6 }
different Object

Object.assign과 같이 target만을 수정하고, 이후 들어오는 source 객체들은 변화가 없다.

lodash merge

로데쉬 라이브러리의 merge기능을 사용하는것도 가능하다.

기본 사용법
const _ = require('lodash');

var obj1 = {a:1,b:2};
var obj2 = {c:3,d:4};
var obj3 = {c:3,d:5,e:6};

var newObj = _.merge(obj1,obj2,obj3);

obj1.a = 3;

console.log(obj1);
console.log(newObj);

if (obj1 === newObj) {
console.log('same Object');
} else {
console.log('different Object');
}

결과값은 다음과 같다.

{ a: 3, b: 2, c: 3, d: 5, e: 6 }
{ a: 3, b: 2, c: 3, d: 5, e: 6 }
same Object