변수(variable)는 하나의 값을 저장하기 위해 확보한 메모리 공간 자체 또는 그 메모리 공간을 식별하기 위해 붙인 이름을 말한다.
JavaScript(이하 JS)에서는 원시유형과 객체라는 두 가지 타입이 있으며, 변수가 객체인지 원시값인지에 따라 메모리에 저장하는 방식이 다르다.
let name = "Samson";
let obj = {
"name" : "Roy",
"age" : 35
}
https://codehandbook.org/variables-in-memory/
원시값은 스택에 자신의 고유 주소와 값(”Samson”)을 가지고,
객체(배열 등)는 스택에 자신의 고유 주소와 값으로 힙영역 주소의 위치(references)를 갖는다. 그리고 힙 영역 메모리의 값으로 할당한 값들(name, age)을 가진다.
이 개념이 중요한 이유는 배열에서 찾을 수 있다.
const의 경우, 변수의 중복 선언과 변수에 대한 재할당이 모두 불가능하다.
const a = 1;
const a = 2; //Error 변수 중복 선언
a = 3; //Error 재할당 불가
console.log(a); // 1
let의 경우, 변수의 중복선언은 불가능하나 재할당은 가능하다.
let a = 1;
let a = 2; //Error 변수 중복 선언
a = 3;
console.log(a); // 3
그렇다면 다음의 경우는 어떨까?
const arr = [];
arr.push(1);
arr.push(2);
arr.push(3);
arr.push(4);
arr.push(5);
const 로 선언했으므로 변수에 대한 재할당이 막히니 오류가 발생할 것이라고 착각하기 쉽다.
하지만 배열(혹은 객체)의 경우 스택영역에 가지고 있는 힙영역의 메모리 주소를 참조하기 때문에 사실상 값이 변하지 않는다.
따라서 위 코드가 실행되면
스택영역의 값은 전혀 변하지 않으며, 힙 영역에서 관리하고 있는 arr이 참조하는 주소가 가지는 값이 [] 에서 [1,2,3,4,5]로 변할 뿐이다.
const, let에서 의미하는 변수의 재할당은 ‘주소’를 의미한다.
다음의 경우는 어떨까?
const arr = [];
arr = ['new']; //Error
이 경우는 스택 영역에 대한 재할당-배열의 재선언-이 되었기 때문에 스택의 value에 있는 참조 주소 자체가 바뀌게 된다. 그러나 const는 이를 허용하지 않는다.
위 같은 경우처럼 재할당을 막고 싶을 때는 const를 쓰면 된다.
var는 다음과 같은 문제점 때문에 더 이상 사용하지 않는 것이 권장된다.
여기서 메모리 구조에 대해 조금 알고 있는 사람은 궁금할 수 있다.
C언어 같은 경우 배열의 메모리를 동적 할당/해제하여 낭비되는 공간(패딩 바이트)을 줄이는데 JS엔진같은 경우는 힙 영역 메모리를 어떻게 관리할까?
JAVA와 마찬가지로 가비지 컬렉터를 사용해 관리한다. (더 이상 참조되지 않는 데이터를 삭제)