-
1. 식별자
어떤 값을 구별해서 식별할 수 있는 고유한 이름을 말한다.
아래의 코드에서 보이는 것처럼 myNumber 는 23이라는 값을 식별할 수 있다.
var myNumber = 23;
이 때, 23 이라는 값을 직접 저장하는 것이 아닌, 이 값을 참조 하고 있는 메모리 주소를 기억해야 한다.
즉, 식별자는 메모리 주소에 붙여진 "이름" 이라고 생각을 해주면 좋을 것 같다.
2. 변수 선언
자바스크립트는 메모리 직접 제어를 통해 발생할 수 있는 에러를 방지 하기 위해서 개발자의 접근을 허용하지 않습니다
.
그렇기 때문에, 10 + 20과 같은 값을 재사용 하기 위해서는 이를 변수에 저장해서 사용을 합니다.
이러한 변수를 사용 하기 위해서는 우선적으로 선언이 이루어지는데,
선언을 한다는 것은
- 값을 저장하기 위한 메모리 공간을 확보
- 확보된 메모리와 변수와 연결
- 연결된 메모리에 값(데이터 영역 주소)을 연결
위의 3가지 과정을 거치는 것을 의미합니다.
이를 하단의 예시와 그림을 통해서 자세히 다루어보겠습니다.
let a; a = 'abc'
메모리 공간이 확보되면, 확보된 메모리와 변수를 연결합니다.
이후, 하단과 같이 메모리에서 값이 저장된 주소를 참조합니다.
*그렇다면 변수/데이터 영역을 나누는 이유는 뭘까요?
예를 들어서, 5 라는 값이 담긴 변수를 500개 선언한다고 가정 해봅시다.
이 때, 변수가 선언된 메모리 영역에 직접 값을 할당을 하는 경우 500개 모두가 메모리에 상주가 되어야합니다.
하지만, 데이터 영역을 분리하여 주소 값만 변수 영역의 값에 할당이 되면 500개의 변수는 '5' 라는 값이 담긴 하나의 주소 값만을 참조함으로 메모리 효율이 증가됩니다.
- 변수 영역에 직접 값을 저장 할 경우
500 개 변수 * 8바이트(Number 자료형) = 4000 바이트
- 데이터 영역에 저장하고 주소를 저장할 경우
500 개 변수 + 8바이트(Number 자료형) = 1008 바이트
3. 변수 호이스팅
아래의 코드는 어떤 결과를 출력할까요?
console.log(score); var score;
다들 잘 아시는 것처럼 undefined 가 출력될 것입니다.
그 이유는, 런타임 이전 단계에서 "코드 평가"가 우선적으로 실행이 되기 때문입니다 :D
하지만 var를 let으로 바꾼다면 어떤 결과가 출력 될까요?
console.log(score); let score;
var와는 다르게 에러(Cannot access 'score' before initialization) 가 출력됩니다.
var의 경우 코드 [ 평가 + 초기화(=undefined) ] 를 동시에 하지만,
let는 평가만을 진행하여 실질적인 값을 부여 받지 않습니다.
4. 값의 할당
값의 할당은 평가와 분리되어 진행이됩니다.
저희는 일반적으로
var score = 80;
이렇게 할당을 위한 선언을 하지만,
자바스크립트는 변수의 선언과 값의 할당을 2단계로 나누어 진행합니다.
console.log(score); // undefined var score; score = 80; console.log(score); // 80
그러면 아까 위에서 언급했던 것과 같이,
- 빈 메모리 탐색 후, 변수는 undefined을 위한 메모리 주소를 할당 받습니다.
- 80을 저장 하기 위해서, 새로운 주소를 할당 받습니다.
console.log(score); // undefined var score; score = 80; console.log(score); // 80
5. 값의 재할당
값의 재할당이 일어나는 경우도 할당과 같은 작업이 발생됩니다.
var score = 80; score = 90;
- 빈 메모리 탐색 → undefined 를 위한 메모리 주소 할당
- 이전 값(undefined)이 있던 공간을 지우고 80을 위한 새로운 메모리 공간 확보
- 이전 값(80)이 있던 공간을 지우고 80을 위한 새로운 메모리 공간 확보
6. 변수 할당
그렇다면, 새로운 변수에 기존 변수를 할당하면 어떤 일이 일어날까요?
let myNumber = 23; let newVar = myNumber
정답은.. myNumber가 가르키고 있는 메모리 주소를 같게 가르킨다는 것입니다.
그렇다면, myNumber에 1을 더하면 newVar의 값은 어떻게 될까요?
자바스크립트 변수의 메모리는 왜 바뀌는가?
1. call by value
자바스크립트는 변수의 "값"을 참조 하고 있습니다.
그래서, 아래와 같이 코드를 작성하면
let a = 10; let b = a;
메모리 내부에서는 다음과 같은 정보들을 저장합니다.
만약 다음과 같이 코드를 작성하면 어떤 일이 일어날까요?
< 정답 >
20이라는 값이 5004번 이라는 "데이터 주소" 담겨있다면,
a를 참조하는 것으로 "@5004" 변경이 됩니다.
반대로 b는 10이 담긴 @5001을 고대로 참조하고 있기 때문에 10을 출력합니다.
console.log(a); // 20 console.log(b); // 10
데이터가 저장된 주소로 저장이 되는 이유
- 자유로운 데이터 변환과 효율적 메모리 관리를 위함.
- 데이터의 변환이 일어나는 경우 공간을 늘리는 작업이 필요함.
2. call by reference
원시값과 달리 객체는 참조형으로 데이터가 할당됩니다.
아래와 같이 객체를 선언 및 할당을 했을 때
let obj1 = { a : 1, b : 'bbb' }
메모리 내부에서는 다음과 같이 저장이 됩니다.
이전과는 다르게, 값이 저장 되있을 것 같은 "5002" 번으로 가면 우리가 원하는 값이 아닌 새로운 메모리 주소가 적혀있습니다.
그리하여, 아까 위의 예시처럼 참조형 데이터의 값을 변경 한다면
obj1.a = 2;
값이 담긴 메모리 주소의 변경이 아닌 "@5001"이 참조하는 "@7103"이라는 녀석이 가지고 있는 데이터가 참조하는 주소가 변경이 됩니다.
고로 obj1.a의 값을 변경해도 obj1 === obj2의 결과는 true입니다.
let obj2 = obj1; obj1.a = 10; console.log(ob1 === obj2); // true
Reference
https://kimbangg.tistory.com/152
https://velog.io/@modolee/core-javascript-01
'Develop > JavaScript' 카테고리의 다른 글
이터레이터 & 제네레이터 ( iterator & generator ) (0) 2021.08.09 [ JavaScript ] 정규식 ( Regular Expression) (0) 2021.08.03 [ JavaScript ] 실행 컨텍스트 (Execution Context) (0) 2021.07.19 [ JavaScript ] let vs var (0) 2021.07.14 [ JavaScript ] This 란 ? (0) 2021.07.14 댓글