관리 메뉴

Bbaktaeho

[JavaScript] Object.assign 그리고 Spread (Object, 객체, 속성 복사, spread) 본문

프로그래밍 (Programming)/자바스크립트 (JavaScript)

[JavaScript] Object.assign 그리고 Spread (Object, 객체, 속성 복사, spread)

Bbaktaeho 2021. 5. 11. 11:56
반응형

들어가며

최근, NestJS 프레임워크로 개발하다가 공식 문서에서 assign 메서드의 예제 코드를 봤다.

NestJS 공식문서

Serialization 문서를 보니 생성자에 Object.assign() 메서드를 사용하고 있다.

여태 이런 꿀팁을 모르고 있어서 정리하기로 했고 스프레드 연산자를 활용한 방법과 비교해보기로 했다. (Partial은 타입스크립트 문법으로 다음에 다뤄보겠습니다)

Object.assign

타겟을 지정한 객체로 다른 객체의 속성을 복사한다.

원형

Object.assign(target, ...sources)

간단한 예제로 파악해보자. (MDN의 첫 예제를 그대로 가져왔다)

 

기본형 예제

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const returnedTarget = Object.assign(target, source);

console.log(target);

console.log(returnedTarget);

출력은 아래와 같다.

{ a: 1, b: 4, c: 5 }
{ a: 1, b: 4, c: 5 }

기존 target 객체의 속성이 변경되거나 추가되었다.

리턴으로 받은 returnedTarget 객체는 사실 target 객체와 같은 객체를 참조하고 있다.

console.log(target === returnedTarget); // true

딱히 리턴은 받을 필요 없다.

위 예제로 알 수 있는 건 같은 속성 이름(키)이 있다면 덮어쓰기가 되며, 새로운 속성 이름이 source에 있다면 target 객체에 추가된다.

 

source가 여러 개 있을 때도 동일하게 동작한다.

const target = { a: 1, b: 2 };
const sources = [
  { b: 4, c: 5 },
  { b: 6, c: 7, d: 8 },
  { b: 9, c: 10, d: 11 },
  { b: 12, c: 13, d: 14, e: 15 },
];

Object.assign(target, ...sources);

console.log(target);

스프레드 연산자로 sources 리스트를 펼쳐서 인자를 넣어줘야 한다. 안 그러면 리스트의 index 값으로 키가 새로 생성되며 target에 속성이 추가된다.

// Object.assign(target, ...sources); 둘이 같다.
Object.assign(target, sources[0], sources[1], sources[2], sources[3]);

스트레드 연산자로 assign 해주면 출력은 아래와 같다.

{ a: 1, b: 12, c: 13, d: 14, e: 15 }

리스트를 그대로 assign 한다면? (...빼고 실행해보세요!)

{
  '0': { b: 4, c: 5 },
  '1': { b: 6, c: 7, d: 8 },
  '2': { b: 9, c: 10, d: 11 },
  '3': { b: 12, c: 13, d: 14, e: 15 },
  a: 1,
  b: 2
}

원형을 꼭 확인하고 사용하자!

 

참조형 예제

sources 객체들 중에 속성 값으로 참조형이 존재한다면 깊은 복사가 이루어지지 않는다. (당연하지만 주의하자)

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];

const target = { arr: arr1 };
const source = {arr: arr2 };

Object.assign(target, source);

console.log(target.arr === source.arr); // true

깊은 복사를 원한다면 다른 방식을 활용하거나 응용하도록 하자.

Spread vs Object.assign

assign을 알기 전에 항상 스프레드 연산자를 활용하여 객체에 속성을 추가하거나 복사해줬다.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const newOb = {...target, ...source};

console.log(newOb); // { a: 1, b: 4, c: 5 }

역시나 출력은 assign과 같다.

 

하지만 둘은 분명한 차이점이 있었다.

불변성(immutable)을 지켜야 된다면 Object.assign을 사용하는 것 보다 스프레드 연산자를 사용하는 것이 좋다.

Object.assign으로 불변성을 지키지 못하는 것은 아닌데 target에 항상 {} 빈 객체를 인자로 전달해야 한다.

const obj = {
  add: (a, b) => a + b,
};

const newObj = { ...obj };
console.log(newObj);

const copy = Object.assign({}, obj);
console.log(copy);

// obj 객체는 불변성

자세한 차이는 아래 Reference에 링크를 참조!

Reference

developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

 

Object.assign() - JavaScript | MDN

Object.assign() 메소드는 열거할 수 있는 하나 이상의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용합니다. 대상 객체를 반환합니다.

developer.mozilla.org

thecodebarbarian.com/object-assign-vs-object-spread.html

 

Object.assign vs Object Spread in Node.js

The Object Rest/Spread Proposal reached stage 4 in 2018, which means it will be included in a future iteration of the ECMAScript spec. It's also been included in Node.js LTS since Node.js 8, so you can safely start using it today. $ node -v v8.9.4 $ node >

thecodebarbarian.com

 

반응형