let myNumber = 23;
let
, var
, const
등으로 변수 또는 함수
등을 발견한다. (런타임 이전)myNumber
라는 변수 식별자가 생성되고, 실행환경의 렉시컬 환경에 저장된다. myNumber
에는 콜스택의 주소값이 저장되고, 콜스택에는 데이터(23)가 저장된다. (런타임)👉 우리가 선언한 변수에는 콜스택 주소값이 저장된다.
👉 원시타입 데이터는 런타임때 콜스택에 저장된다.
let myNumber = 23;
let newVar = myNumber;
👉 myNumber와 newVar에는 같은 콜스택 주소값이 할당된다.
👉 값을 복사하거나, 같은 값을 가진다면, 콜스택의 새로운 주소를 할당받는 것이 아니라 같은 주소를 갖는다는 것!
같은 콜스택 주소값을 가지고 있은 식별자들이 여러개가 있을 수 있는데, 만약 그 중 하나라도 값이 변경되면, 나머지 콜스택 주소를 참조하는 값들도 다 변경되어야할까?
myNumber = myNumber + 1;
23+1 = 24
가 된다.👉 같은 주소값을 참조하고 있는 식별자들 중 하나가 데이터가 변경되면, 그 식별자는 새로운 주소값을 할당받는다.
👉 만약 더이상 어느 식별자도 콜스택 주소값을 사용하고 있지 않으면 이때 가비지 콜렉터가 실행된다.
let myArray = [];
let
, var
, const
등으로 변수 또는 함수
등을 발견한다. (런타임 이전)myArray
라는 변수 식별자가 생성되고, 실행환경의 렉시컬 환경에 저장된다. []
)가 저장된다. (런타임)myArray.push("first");
myArray("second");
myArray("third");
myArray("fourth");
myArray.pop();
👉 원시타입과 다르게 참조타입의 데이터는 메모리 힙에 저장된다. 따라서, push, pop 등으로 저장된 값을 변경하더라도, 첫째, 배열이 저장된 메모리힙의 주소는 변경되지 않고, 둘째, 콜스택에 저장된 메모리힙의 주소도 변경되지 않고, 셋째, 식별자에 할당된 콜스택의 주소도 변경되지 않는다.
🔍 const는 재할당이 안된다고 했는데 배열과 객체의 데이터 변경이 가능한 이유는?
const는 재할당이 안된다. 여기서 재할당이란, 새로운 주소값을 할당받는 것을 말한다. const로 선언된 배열과 객체를 변경할때, 메모리힙의 주소값이 변경되지 않으므로 콜스택 주소값도 변경되지 않는다. 데이터를 변경했으니까 재할당이 되는 것 아니야?
라고 생각할 수 있지만, 여전히 같은 콜스택 주소를 가리키고, 같은 메모리힙 주소를 가리키므로, 데이터의 변경은 재할당이 아니다!
바로 위에서 재할당이란, 새로운 주소값을 할당받는 것이라고 했다. 그리고 const 키워드로 선언한 데이터는 재할당이 불가능하다.
다음 예시를 살펴보도록 하자.
const myArray = [];
myArray = 3;
👉 myArray
는 참조타입이므로 메모리 힙에 빈배열이 저장되었다.
👉 myArray
에 3을 재할당하려고 하면, 3은 원시타입이므로 식별자 myArray
에는 새로운 콜스택 주소값을 할당하고, 3을 저장하려고 할 것이다. 그런데, 이미 식별자 myArray
에는 콜스택 주소값이 할당되어있으므로 재할당할 수 없다는 에러가 발생할 것이다.
reference