자바스크립트 프로그래밍을 하다 보면 여러 객체를 합쳐야 하는 경우가 많이 발생한다. 이 때 여러가지 방법이 있는데 하나씩 알아보자.
객체에 스프레드 프로퍼티 문법(...
)을 사용해서 합치려는 객체를 각각 펼친 후 하나의 객체로 만들 수 있다.
const obj1 = { key1: 'val1' };
const obj2 = { key2: 'val2' };
const merged = { ...obj1, ...obj2 }; // { key1: 'val1', key2: 'val2' }
Object.assign()
메서드 사용스프레드 프로터피 문법과 함께 TC39 stage4에 제안된 Object.prototype.assign
을 사용해서 객체를 복사할 수 있다. 형식은 아래와 같고, source를 target에 복사해서 반환하는 형태다.
assign(target: object, ...sources: any[]): any;
const obj1 = { key1: 'val1' };
const obj2 = { key2: 'val2' };
const merged = Object.assign({}, obj1, obj2); // { key1: 'val1', key2: 'val2' }
Object.assign()
함수는 새로운 객체를 반환하는게 아닌 target 객체를 변경시키는 방식으로 작동하므로 주의가 필요하다. immutable
하게 사용해야 하면 위에처럼 target
에 빈 객체 리터럴을 넣어주는 방식으로 사용할 수 있다.
두가지 방법 모두 한계가 있는데, 중첩 객체
를 병합할 때가 그렇다.
const obj1 = {
key1: 'val1',
key2: {
a: 'A'
}
}
const obj2 = {
key1: 'val2',
key2: {
b: 'B'
}
}
const merged1 = {...obj1, ...obj2};
const merged2 = Object.assign({}, obj1, obj2);
// 둘 모두 { key1: 'val2', key2: { b: 'B' }}
두가지 문법 모두key2
의 값은 뒷쪽에 사용된 객체의 값으로 덮어썼다. 하지만 { a: 'A', b: 'B' }
로 만들어야 하는 경우는 생긴다.
직접 객체를 병합하는 반복문같은걸 만들수 있겠지만 번거로운 일이다. lodash
의 merge
를 사용하면 간단하게 해결할 수 있다.
interface LoDashStatic {
// ...
merge(object: any, ...otherArgs: any[]): any;
// ...
}
import * as _ from 'lodash';
describe('test', () => {
fit('객체 병합 테스트', () => {
const obj1 = {
key1: 'val1',
key2: {
a: 'A'
}
};
const obj2 = {
key1: 'val2',
key2: {
b: 'B'
}
};
const merged = _.merge({}, obj1, obj2);
expect(merged).toEqual({ key1: 'val2', key2: { a:'A', b: 'B' }}); // true
});
});
lodash
의 merge
는 Object.assign
와 비슷하게 작동한다. 첫째 인자로 받은 targe 객체에 뒤의 source 객체들을 깊은 merge 한 후 targe 객체를 반환한다. 따라서 새로운 객체를 생성하진 않으므로 immutable하게 하려면 위의 방식처럼 빈 객체 리터럴을 target에 넣어주면 될 것 같다.
lodash의 다른 기능도 파보면 유용할 것 같다.