자바스크립트: Spread(...) 연산자

Choizz·2023년 2월 28일
0

이번 포스팅은 자바스크립트의 Spread 연산자에 대한 것 입니다. vue에서 자바스크립트를 사용하면서 Spread 연산자를 사용할 일이 있었고, 내용을 정리할 겸 포스팅하려고 합니다.

아래 식 처럼 복사를 하게 되면, arr의 값이 copyArr에 복사된 것이긴 하지만, 같은 주소값을 공유하게 됩니다.
따라서, copyArr의 값에 변화가 일어나면, arr도 동일하게 변화가 일어납니다. (이것은 자바에서도 마찬가지)

const arr = [1,2,3,4,5];
const copyArr = arr;

arr[1] = 8;
console.log(copyArr);
//[1, 8, 3, 4, 5]

Spread 연산자

Spread 연산자를 이용한다면, 배열이나 객체의 요소들만을 다른 배열에 복사가 가능합니다.
Spread 연산자는 배열에 있는 값들을 전개해주는 연산자입니다. []나 {}가 벗겨진다고 생각하면 됩니다.

  • ...을 붙입니다.
const arr = [1,2,3,4,5];
console.log(...arr);
//1,2,3,4,5 <- []가 벗겨짐.

Spread 연산자를 이용해서 []를 벗긴 뒤, 이것을 다시 []로 감싼다면, 동일한 값으로 복사가능하게 됩니다.
이렇게 되면, 값은 같지만, 주소값이 다른 배열로 복사가 가능하게 됩니다. 즉, arr의 값을 변경해도 copyArr에는 전혀 영향이 가지 않게 됩니다.

const arr = [1,2,3,4,5];
const copyArr = [...arr];

arr[1] = 9;
console.log(arr);
//[1, 9, 3, 4, 5]

console.log(copyArr);
//[1, 2, 3, 4, 5]

얕은 복사와 깊은 복사

얕은 복사(shallow copy)

위의 코드처럼 복사를 하는 것을 얕은 복사(shallow copy)라고 합니다.
객체를 이용해서 예를 다시 한번 들어보겠습니다.

  • person이라는 객체를 하나 만들고 이것을 얕은 복사를 해보겠습니다.
    - 객체의 {}를 벗겨내고, 다시 {}를 씌운 후 다시 객체에 할당해 줍니다.
const person = {
	name : "kim",
  	age : 10,
}

const copyPerson = {...person}
console.log(copyPerson);
//{name: 'kim', age: 10}

얕은 복사를 할 때 주의할 점

그렇다면, 아래의 경우는 어떻게 될까요?

  • 우선 객체 하나를 만들겠습니다. 여기에 객체 요소를 하나 추가했습니다.
  • 그 후 얕은 복사를 해보겠습니다.
const person = {
	name : "kim",
  	age : 10,
  	number : {num1:1, num2:2}
}

const copyPerson = {...person}
console.log(copyPerson);
/*{
	name : "kim",
  	age : 10,
  	number : {num1:1, num2:2}
  }*/

얕은 복사를 한 후 copyPerson의 요소를 바꿔보겠습니다.

  • copyPerson의 데이터들이 바뀌었습니다.
copyPerson.name = "choi";
copyPerson.age = 20;
copyPerson.number.num1 = 5;

console.log(copyPerson);
/*{
	name : "choi",
  	age : 20,
  	number : {num1:5, num2:2}
  }*/

그렇다면, person의 데이터는 그대로일까요?

  • name과 age는 바뀌지 않았지만, number의 num1이 바뀌었습니다.
console.log(person);
/*{
	name : "kim",
  	age : 10,
  	number : {num1:5, num2:2}
  }*/

이렇게 되는 이유는,

person과 copyPerson의 주소값은 다르지만, 이 두 객체에 들어있는 number라는 객체의 주소값은 동일하게 복사됩니다. 즉, number 객체의 주소값(Heap에 저장)은 공유하게 되는 것 입니다.

다시 말해서, 얕은 복사를 하더라도, 그 객체 안에 요소로 있는 배열이나 객체의 주소값은 바뀌지 않기 때문에 person이나 copyPerson의 객체 값에 변화가 일어난다면, 두 객체 모두 적용되게 됩니다.

깊은 복사(deep copy)

만약 객체 안에 배열이나 객체가 들어있고, 이 객체를 복사하려 할 때, 원본과 복사본 서로에게 영향을 주지 않으려면 깊은 복사를 해야합니다.

  • 깊은 복사를 위해선 JSON.stringify()JSON.parse()가 필요합니다.
  • JSON.stringify()를 이용해서 객체를 모두 문자화 한 뒤,
  • JSON.parse()로 다시 객체로 바꾼 뒤 할당해 주면 됩니다.
const person = {
	name : "kim",
  	age : 10,
  	number : {num1:1, num2:2}
}

const copy = JSON.stringify(person); //객체를 Json형태의 문자로 변환
//'{"name":"kim","age":10,"number":{"num1":1,"num2":2}}'

const copyPerson = JSON.parse(copy);
/*{
	name : "kim",
  	age : 10,
  	number : {num1:1, num2:2}
  }*/

이제 person이나 copyPerson안에 있는 number 객체의 값에 변화를 줘도, 독립적으로 변화가 된다.


Reference

profile
집중

0개의 댓글