Javascript 객체 복사하기(1)
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"]
세줄 요약
- 원시형과 객체형 데이터의 복사방법은 다르다.
- 원본데이터를 직접 건드려야 할 때는 이게 맞나 생각해보자.
- Object.assign()과 스프레드 연산자를 쓰자
참고
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
Object.assign() - JavaScript | MDN
Object.assign() 메서드는 출처 객체들의 모든 열거 가능한 자체 속성을 복사해 대상 객체에 붙여넣습니다. 그 후 대상 객체를 반환합니다.
developer.mozilla.org