그럼에도 불구하고

👨‍💻

[JavaScript] 변수 호이스팅 본문

JavaScript/JavaScript basics

[JavaScript] 변수 호이스팅

zenghyun 2022. 12. 23. 11:33

 

지난번에 다뤄본 변수 호이스팅을 변수별로 알아보자

 

 

[ 변수 선언의 실행 시점과 변수 호이스팅 ]

 

console.log(score); // undefined

var score; // 변수 선언문

 

위의 예제에서는 변수 선언문보다 변수를 참조하는 코드가 앞에 있다. 자바스크립트 코드는 인터프리터에 의해 한 줄씩 순차적으로 실행되므로 console.log(score);가 가장 먼저 실행되고 순차적으로 다음 줄에 있는 코드를 실행한다. 따라서 console.log(score);가 실행되는 시점에는 아직 score 변수의 선언이 실행되지 않았으므로 참조 에러(ReferenceError)가 발생할 것처럼 보인다. 하지만 참조 에러가 발생하지 않고 undefined가 출력된다. 

 

 

그 이유는 변수 선언이 소스코드가 한 줄씩 순차적으로 실행되는 시점, 즉 런타임(runtime)이 아니라 그 이전 단계에서 먼저 실행되기 때문이다.

 

★ 자바스크립트 엔진은 소스코드를 한 줄씩 순차적으로 실행하기에 앞서 먼저 소스코드의 평과 가정을 거치면서 소스코드를

실행하기 위한 준비를 한다. 이때 소스코드 실행을 위한 준비 단계인 소스코드의 평가 과정에서 자바스크립트 엔진은 변수 선언

을 포함한 모든 선언문(변수 선언문, 함수 선언문 등)을 소스코드에서 찾아내 먼저 실행한다. 그리고 소스코드의 평가 과정이 끝

나면 비로소 변수 선언을 포함한 모든 선언문을 제외하고 소스코드를 한 줄씩 순차적으로 실행한다.

 

즉, 자바스크립트 엔진은 변수 선언이 소스코드의 어디에 있든 상관없이 다른 코드보다 먼저 실행된다.

따라서 변수 선언이 소스코드의 어디에 위치하는지와 상관없이 어디서든지 변수를 참조할 수 있다. 

이처럼 변수 선언문이 코드의 선두로 끌어올려진 것처럼 동작하는 자바스크립트 고유의 특징을 

변수 호이스팅(variable hoisting)이라 한다.

 

 

하지만, 변수 호이스팅은 변수 생성 및 초기화와 할당이 분리되어 진행된다.

호이스팅 된 변수는 undefined로 초기화되고 실제 값의 할당은 할당문에서 이루어진다는 것을 명심해야 한다.

 

https://despiteallthat.tistory.com/46

 

[JavaScript] 변수 선언 / 변수 호이스팅 / 값의 할당

오늘은 변수 선언 / 변수 호이스팅 / 값의 할당에 대해 알아보자 [ 변수 선언 ] 변수 선언(variable declaration)이란 변수를 생성하는 것을 말한다. 좀 더 자세히 말하면 값을 저장하기 위한 메모리 공

despiteallthat.tistory.com

 

 


 

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
Comments