[TIL] 배열을 상수로 선언해도 값이 변경되는 이유

cheo·2021년 8월 6일
1

TIL

목록 보기
1/5

질문

  • Q1. const arr = []와 같이 배열을 상수로 선언해도 push가 동작하는 이유는 무엇일까?

답변

TL;DR

  • 배열은 참조 타입이기 때문에 값이 콜 스택 메모리가 아닌 힙 메모리에 저장되고 힙 메모리에 있는 값은 변경이 가능하다.

자바스크립트 메모리

자바스크립트의 메모리는 다음과 같이 두 가지로 나뉜다:

  • 콜 스택(call stack) 메모리
  • 힙(heap) 메모리

원시 타입의 메모리 사용

let a = 126;
a = 127;

자바스크립트에서 원시 타입(primitive type)은 변경이 불가능하다. 따라서 원시 타입의 값이 변경될 때는 항상 메모리가 새로 할당된다. 위 예제를 보면 변수 a는 값 126을 저장하는 메모리 영역 A를 바라본다. 그러나 변수 a의 값을 127로 변경하면, 숫자 데이터는 원시 타입이므로 메모리 영역 A의 값을 변경할 수 없어서 새로운 메모리 영역 B를 새로 할당해서 127을 저장한다. 즉, 변수 a가 바라보는 메모리 주소가 변경된다.

이제 다음 예제 코드를 예측할 수 있다.

let a = 126;
let b = a;
a = 127;

console.log(b)
// ?

126이 나온다. 왜냐하면 변수 b가 바라보고 있는 곳은 값이 변경되기 전 변수 a가 바라보고 있던 메모리 영역이기 때문이다.

참조 타입의 메모리 사용

다음과 같이 배열을 상수로 선언했는데 push로 값이 추가되는 이유는 무엇일까?

const arr = [];
arr.push(1);
arr.push(2);

console.log(arr) // [1, 2]

배열은 object 타입이라 참조 타입(reference type)으로 분류된다. 배열을 선언하면 힙 메모리에 배열이 선언된다. 콜 스택에 선언된 배열 변수는 힙에서 생성된 배열의 메모리 주소를 참조(reference)한다.

이미지 출처: medium - JavaScript’s Memory Model by Ethan Nam

힙 메모리는 동적으로 크기가 변할 수 있다. 배열에 값을 추가하면 그대로 힙 메모리에 할당된다.

이미지 출처: medium - JavaScript’s Memory Model by Ethan Nam

결론적으로 배열을 상수로 선언해도 push가 동작하는 이유는 콜 스택에 할당된 메모리를 변경하는 것이 아니라 힙 메모리를 변경하는 것이기 때문이다.

응용

다음 코드를 예측할 수 있다.

const a = [1, 2, 3];
const b = a;
a[0] = 100;

console.log(b[0])
// ?

100을 출력한다. 배열은 참조 타입이므로 변수 a가 바라보는 메모리 주소는 변경되지 않는다. 따라서 변수 b는 변수 a와 같은 메모리 주소를 참조한다.

See also

0개의 댓글