Day 14 - Javascript References VS Copying

Reference(참조)와 Copy(복사)에 대한 전반적인 개념을 다룬다. 개인적으로 자바스크립트의 속성을 이해하기 위해 정말 필요한 과제였다고 생각한다.

값 복사 (number, String)

1
2
3
4
5
let age = 100;
let age2 = age;
console.log(age, age2); // 100, 100
age = 200;
console.log(age, age2); // 200, 100

값은 별도의 방법없이 대입 선언만으로 복사할 수 있다. 예시는 숫자인데 문자열(String)도 마찬가지다.

배열 복사

배열은 값을 복사할 때 처럼 =로는 할 수 없다. 그러면 “복사”가 아닌 “참조”가 돼서 복사된 (것처럼 보이는) 배열의 요소가 변경되면 원래의 배열도 바뀌게 된다. 당연히 참조되었기 때문에 이런 일이 발생한다.

배열을 복사하는 방법은 많다.

1
2
3
4
5
6
const players = ["Wes", "Sarah", "Ryan", "Poppy"];

const team2 = players.slice();
const team3 = [].concat(players);
const team4 = [...players];
const team5 = Array.from(players);

players 배열을 복사하기 위해 사용할 수 있는 4가지 방법이고, 결과는 모두 같다. 나는 ...을 사용하는 ES6 Spread 방법이 가장 마음에 든다. 참고로 slice()concat()으로 복사가 가능한 이유는 대상이 되는 배열을 가지고 새로운 배열을 반환하기 때문이다.

객체(Object) 복사

One Level Copy - Object.assign()

복사의 대상이 되는 배열은

1
2
3
4
const person = {
name: "Zini",
age: 24,
};

person 객체이다. 당연히 =를 사용하면 복사가 아닌 참조가 되어버린다.

1
const personCopy = Object.assign({}, person, { number: 99 });

Object.assign을 사용해서 person 객체를 다시 객체화시켜 복사하는 방법이 있다.

나중에는 배열에서 spread를 사용한 것처럼 {...person}으로 복사가 가능해질 것 같다. 참고로 Chrome에서는 현재 지원한다고 한다.

One Level 이상의 Copy - JSON.parse(JSON.stringify())

복사할 대상이

1
2
3
4
5
6
7
8
const zini = {
name: "Zini",
age: 24,
social: {
github: "zinirun",
instagram: "@normalzini",
},
};

이렇게 1레벨이 아닌 2레벨로 구성되어 있다면, 앞의 방법처럼 Object.assign()을 사용할 수 없다. 1레벨만 복사되고 2레벨부터는 참조되기 때문에 2레벨의 요소가 변경되면 원 배열의 값도 바뀐다.

1
const ziniCopy = JSON.parse(JSON.stringify(zini));

JSON을 사용하여 JSON 객체로 stringify 후 parse하면 레벨에 관계없이 복사할 수 있다. 당연히 1레벨도 복사할 수 있기 때문에 나는 객체를 복사할 때는 항상 JSON을 사용할 것 같다.