console.log(test);
var test;
test = 30;
console.log(test);
이 코드의 실행 결과는 무엇일까?
첫 console.log
에 있는 test는 선언되기 전이기 때문에 ReferenceError
가 발생하게 될까?
결과가 어떻게 출력되는지는 JS의 변수에 관해 알아야 한다.
1️⃣ 변수 선언
변수를 사용하기 위해서는 반드시 선언이 필요하다.
변수를 선언하기 위해서는 var
, const
, let
키워드를 사용한다.
이때, 변수 선언에 의해 확보된 메모리 공간에 값을 할당하지 않으면 JS 엔진에 의해 undefined
라는 값이 할당되어 초기화 된다.
- 선언: 변수 이름을 등록해서 JS 엔진에 변수의 존재를 알린다
- 초기화: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로
undefined
를 할당해 초기화
JS의 이러한 초기화 단계는 할당된 메모리에 undefined
를 할당하여 이전에 남아있던 쓰레기 갚을 덮는다.
그 결과, 참조할 때 쓰레기 값이 나오는 위험이 감소한다.
키워드
키워드는 JS 코드를 해석하고 실행하는 JS 엔진이 수행할 동작을 규정한 일종의 명령어이다.
키워드를 만나면 자신이 수행해야 할 약속된 동작을 수행한다.
예를 들어, 위의 변수 선언 키워드인 var
를 쓰게 되면 JS 엔진은 var
뒤에 오는 변수 이름으로 새로운 변수를 선언한다.
2️⃣ 값의 할당
값을 할당하기 위해 =
을 사용한다.
우변의 값을 좌변의 변수에 할당한다.
값의 재할당
이미 값이 할당되어 있는 변수에 새로운 값을 다시 할당하는 것이다.
상수
값을 재할당할 수 없어서 변수에 저장된 값을 변경할 수 없는 것이다.
즉, 한 번만 할당할 수 있는 변수이다.
const
키워드를 사용하여 선언한다.
값의 할당의 메모리
변수에 값을 할당/재할당 할 때는 새로운 메모리 공간을 확보하고 그곳에 할당 값을 저장한다.
var score;
score = 80;
score = 90;
위와 같이 score 변수를 선언하고 80의 값을 할당, 90의 값을 재할당 하는 경우를 생각해보자.
var score
를 통해 변수를 선언하게 되면 메모리 주소 1에 undefined
로 초기화 된다.
score = 80
을 통해 값을 할당하게 되면 메모리 주소 1의 내용이 80으로 바뀌어 저장되는 것이 아니라, 새로운 메모리 주소(메모리 주소 2)에 저장된다.
마찬가지로, score = 90
을 통해 값을 재할당 하게 되면 새로운 메모리 주소(메모리 주소 3)에 저장된다.
결과적으로, 위의 코드가 실행되면 메모리 주소 1, 2, 3에 각각 undefined
, 80, 90이 저장되어 있다.
가비지 콜렉터
위의 예시에서 마지막으로 할당된 90의 값만 사용하고 undefined
와 80은 메모리에 저장되어 있지만 더 이상 필요하지 않다.
이때, 가비지 콜렉터에 의해 메모리에서 해당 값들은 자동 해제된다.
단, 언제 해제되는지는 예측할 수 없다.
3️⃣ 변수 호이스팅
변수 선언이 런타임(소스코드가 한 줄씩 순차적으로 실행되는 시점)이 아니라 그 이전 단계에서 먼저 실행된다.
JS 엔진은 소스코드의 평가 과정을 거치면서 소스코드를 실행하기 위한 준비를 한다.
소스코드 평가 과정에서 JS 엔진은 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아 먼저 실행한다.
소스코드의 평가 과정이 끝나면 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행한다.
결과적으로, 변수 선언이 소스코드의 어디에 있든 다른 코드보다 먼저 실행된다.
console.log(score);
var score;
// 기대 출력 -> ReferenceError / 실제 출력 -> undefined
따라서, 위의 코드를 실행했을 때, 프로그램이 실행되기 전 var score;
가 가장 먼저 실행되어 score라는 변수가 선언된다.
그 이후, 런타임에서 console.log
가 실행된다.
score를 선언했지만 값을 할당하지 않았기 때문에 undefined
로 초기화 되어 있다.
따라서, 해당 코드는 undefined
를 출력한다.
이러한 특징을 변수 호이스팅이라 하며 이는 변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징이다.
주의할점은 변수의 선언은 호이스팅되어 런타임 이전에 실행되지만 값의 할당은 런타임에 실행된다는 것이다.
console.log(test);
var test = 30;
console.log(test);
// 실행결과 -> undefined / 30
위와 같이 선언과 동시에 값을 할당하더라도 변수 선언만 런타임 이전에 수행되어 첫 console.log
에서는 undefined
가 출력되고 프로그램이 실행되며 값이 할당되어 두번째 console.log
에서는 30이 출력된다.
💡 결론
console.log(test);
var test;
test = 30;
console.log(test);
처음에 봤던 이 코드의 실행결과는 undefined
와 30이 된다.
var test
가 가장 먼저 실행되어(변수 호이스팅) undefined
로 초기화 되고 런타임에서 첫 console.log
가 실행된다.
따라서, 첫 console.log
의 결과는 undefined
가 된다.
이후, test = 30;
이 실행되어 30이라는 값이 test라는 변수에 할당된다.
따라서, 두번째 console.log
의 결과는 30이 된다.
console.log(test);
test = 30;
var test;
console.log(test);
코드를 위와 같이 수정해도 변수 호이스팅에 의해 var test
가 가장 먼저 실행되므로 결과에는 변함이 없다.
'개발 > JavaScript' 카테고리의 다른 글
[NodeJS] 싱글 스레드와 이벤트 루프 (0) | 2023.07.29 |
---|---|
[JavaScript] 싱글 스레드와 비동기 (0) | 2023.07.23 |
[JavaScript] 함수 (0) | 2023.02.02 |
[JavaScript] 원시 값과 객체 (0) | 2023.01.21 |
[JavaScript] 객체 (0) | 2023.01.07 |