삐옹

Javascript 객체 복사하기(1) 본문

Javascript

Javascript 객체 복사하기(1)

삐옹 2022. 5. 27. 16:10

 

Object는 알다가도 모를 놈이다.

복사한다고 했는데, 원본 바뀐다고 얘도 똑같이 바뀌면 어쩌자는거지.

에 대한 해결법이다.

 

상황

user1에 있는 데이터를 user2에 복사한 뒤

user1에 수정이 일어났을 때 무슨 일이 일어날까.

(user1의 데이터 타입이 *원시형일때와 **객체형 일 때 두가지 상황으로 나눠 설명합니다.)

 

*원시형(primitive type)

  • String
  • Boolean
  • null
  • undefined
  • symbol (ES6에서 추가됨)

**객체형(object/reference type)

  • object

원시 타입 데이터 복사

user1에 "mike"를 넣고, user2에 user1을 복사 해줍니다. 

let user1 = "mike";
let user2 = user;
console.log(user1) // mike

그런데 실수를 했네요

user1에는 "mike가 아니라" "bob"을 넣었어야했습니다.

user1을 변경해주겠습니다.

let user1 = "mike";
let user2 = user;

user1 = "bob"; // "mike" -> "bob" 으로 변경합니다
console.log(user1); // bob
console.log(user2); // mike

user1을 콘솔을 찍어보니 "bob"으로 변경이 잘 이루어진걸 확인할 수 있습니다. 

user2에는 실수로 기입했던 "mike"값이 그대로 들어있습니다.

 

이렇게 원시형 데이터를 복사했을 때는

자연스럽게 원본과 사본 데이터가 독립적입니다.

(이것을 객체복사에서는 다른 reference를 보고 있다고 말합니다.)

객체 타입 데이터 복사 

유저의 정보를 조금 더 세분화 시켜보겠습니다.

let user1 = {name : "bob", age : 31};
let user2 = user1;

console.log(user1); // {name: 'bob', age: 31}
console.log(user2); // {name: 'bob', age: 31}

신경써야할 정보가 조금 더 늘었지만

역시나 user2에도 복사가 잘 이루어졌습니다.

 

이번에는 bob씨의 나이가 잘 못 기입되었다고 하네요.

수정해보겠습니다.

 

user1.age = 19;

console.log(user1); // {name: 'bob', age: 19}
console.log(user2); // {name: 'bob', age: 19}

변경이 잘 이루어졌습니다.

그런데 복사본 user2의 나이도 바뀌어버렸습니다.

 

user2가 변경되지 않게하려면 총 3가지 방법이 있습니다.

1. 빈 객체 생성해서 for문으로 값 넣어주기   (old)
2. Object.assign       (new)
3. Spread 연산자        (new)

 

빈 객체 생성해서 for문으로 값 넣어주기

let user1 = {name : "bob", age : 31};
let user2 = {};
for(key in user1){
    user2[key] = user1[key];
}

user1.name = "steven"

console.log(user1) // {name: 'steven', age: 31}
console.log(user2) // {name: 'bob', age: 31}

 

Object.assign() 함수

let user1 = {name : "bob", age : 31};
let user2 = {};
Object.assign(user2, user1); // Object.assign(새로 만들 변수, 복사할 변수)

user1.name = "steven"

console.log(user1) // {name: 'steven', age: 31}
console.log(user2) // {name: 'bob', age: 31}

역시 같습니다.

 

let user1 = {name : "bob", age : 31};

let user2 = Object.assign({}, user1);

user1.name = "steven"

console.log(user1) // {name: 'steven', age: 31}
console.log(user2) // {name: 'bob', age: 31}

3. Spread 연산자

let user1 = {name : "bob", age : 31};
let user2 = {...user1};

user1.name = "shallon";

console.log(user1); // {name: 'shallon', age: 31}
console.log(user2); // {name: 'bob', age: 31}

배열을 복사할 때도 똑같이 쓰면됩니다.

let user2 = ["mike", "chloe", "bob"]
let user1 = [...user2]; 

user1[0] = "venny";

console.log(user1) // ["venny", "chloe", "bob"]
console.log(user2) // ["mike", "chloe", "bob"]

 

 


세줄 요약

  1. 원시형과 객체형 데이터의 복사방법은 다르다.
  2. 원본데이터를 직접 건드려야 할 때는 이게 맞나 생각해보자.
  3. Object.assign()과 스프레드 연산자를 쓰자

 

참고

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

 

Object.assign() - JavaScript | MDN

Object.assign() 메서드는 출처 객체들의 모든 열거 가능한 자체 속성을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환합니다.

developer.mozilla.org