일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- media query
- 그럼에도불구하고
- react-router-dom
- TypeScript
- 코드업
- frontend
- JavaScript
- CSS
- redux
- 코딩테스트
- java
- @media
- 자바
- coding
- max-width
- HTML
- cleancode
- Servlet
- JS
- git
- node
- 자바문제풀이
- 반응형 페이지
- node.js
- github
- 프론트엔드
- 변수
- 그럼에도 불구하고
- webpack
- react
- Today
- Total
그럼에도 불구하고
[JavaScript] 변수 호이스팅 본문
지난번에 다뤄본 변수 호이스팅을 변수별로 알아보자
[ 변수 선언의 실행 시점과 변수 호이스팅 ]
console.log(score); // undefined
var score; // 변수 선언문
위의 예제에서는 변수 선언문보다 변수를 참조하는 코드가 앞에 있다. 자바스크립트 코드는 인터프리터에 의해 한 줄씩 순차적으로 실행되므로 console.log(score);가 가장 먼저 실행되고 순차적으로 다음 줄에 있는 코드를 실행한다. 따라서 console.log(score);가 실행되는 시점에는 아직 score 변수의 선언이 실행되지 않았으므로 참조 에러(ReferenceError)가 발생할 것처럼 보인다. 하지만 참조 에러가 발생하지 않고 undefined가 출력된다.
그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임(runtime)이 아니라 그 이전 단계에서 먼저 실행되기 때문이다.
★ 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평과 가정을 거치면서 소스코드를
실행하기 위한 준비를 한다. 이때 소스코드 실행을 위한 준비 단계인 소스코드의 평가 과정에서 자바스크립트 엔진은 변수 선언
을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아내 먼저 실행한다. 그리고 소스코드의 평가 과정이 끝
나면 비로소 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행한다.
즉, 자바스크립트 엔진은 변수 선언이 소스코드의 어디에 있든 상관없이 다른 코드보다 먼저 실행된다.
따라서 변수 선언이 소스코드의 어디에 위치하는지와 상관없이 어디서든지 변수를 참조할 수 있다.
이처럼 변수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징을
변수 호이스팅(variable hoisting)이라 한다.
하지만, 변수 호이스팅은 변수 생성 및 초기화와 할당이 분리되어 진행된다.
호이스팅 된 변수는 undefined로 초기화되고 실제 값의 할당은 할당문에서 이루어진다는 것을 명심해야 한다.
https://despiteallthat.tistory.com/46
var 키워드로 선언한 변수와 달리 let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 동작한다.
console.log(num); // ReferenceError : num is not defined
let num;
위의 예제처럼 let 키워드로 선언한 변수를 변수 선언문 이전에 참조하면 참조 에러(ReferenceError)가 발생한다.
var 키워드로 선언한 변수의 경우 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 "선언 단계"와 "초기화 단계"가 한 번에 진행된다.
하지만, let 키워드로 선언한 변수는 "선언 단계"와 "초기화 단계"가 분리되어 진행된다.
즉, 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만 초기화 단계는 변수 선언문에 도달했을 때 실행된다.
그래서 초기화 단계가 실행되기 이전에 변수에 접근하면 참조 에러가 발생하는 것이다.
다시 말해 let 키워드로 선언한 변수는 스코프의 시작 지점부터 초기화 단계 시작 지점(변수 선언문)까지 변수를 참조할 수 없다.
시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 일시적 사각지대(Temporal Dead Zonel ;TDZ)라고 부른다.
// 런타임 이전에 선언 단계가 실행된다. 아직 변수가 초기화되지 않았다.
// 초기화 이전의 일시적 사각 지대에서는 변수를 참조할 수 없다.
console.log(num); // ReferenceError: foo is not defined
let num; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(num); // undefined
num = 1; // 할당문에서 할당 단계가 실행된다.
console.log(num); // 1
위의 예제를 보면 let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보인다.
하지만 그렇지 않다.
let foo = 1; // 전역 변수
{
console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
let foo = 2; // 지역 변수
}
let 키워드로 선언한 변수에서 변수 호이스팅이 발생하지 않는다면 위 예제는 전역 변수 foo의 값인 1을 출력해야 한다.
하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 대문에 참조 에러가 발생한다.
이는 const에서도 마찬가지다.
const num = 10;
{
// 변수 호이스팅이 발생하지 않는 것처럼 동작한다
console.log(num); // ReferenceError: Cannot access 'num' before initialization
const num = 1;
console.log(num); // 1
}
// 블록 레벨 스코프를 갖는다.
console.log(num); // 10
'JavaScript > JavaScript basics' 카테고리의 다른 글
[JavaScript] 자바스크립트 내장 객체 (0) | 2022.12.28 |
---|---|
[JavaScript] 이벤트와 각종 이벤트 처리기 (0) | 2022.12.27 |
[JavaScript] 전역 변수의 문제점 (0) | 2022.12.23 |
[JavaScript] 스코프(scope)란? (0) | 2022.12.21 |
[JavaScript] Immutability와 mutable (0) | 2022.12.19 |