자바스크립트의 특징, 호이스팅(hoisting)이란?

잭슨·2023년 12월 16일
0

javascriprt

목록 보기
2/11
console.log(score); //undefined
var score;

위 소스코드를 실행시키면 undefined가 출력된다.
뭔가 이상하다. 자바스크립트는 컴파일러가 아니라 인터프리터로 코드를 번역하기 때문에 위에서부터 차례대로 한 줄 씩 소스 코드를 실행시킨다. 또한 선언되지 않은 변수를 참조할 경우 ReferenceError를 출력한다. 위 코드는 변수가 생성되기 전에 변수를 참조했음에도 불구하고 에러가 발생하지 않는다.
즉, console.log(score); 가 실행될 때는 아직 score변수가 생성되지 않았으므로 ReferenceError가 출력되어야 정상이지만 실제로는 undefined가 출력된다.
이제 그 이유를 알아보자.

호이스팅

자바스크립트는 소스코드가 실제로 실행되는 단계인 런타임 이전에 소스코드 평가 과정을 거치는데, 이 과정에서 자바스크립트 엔진은 변수의 선언을 포함한 모든 선언문을 먼저 실행시킨다. 이처럼 모든 선언문을 스코프의 가장 선두로 끌어 올린 것처럼 동작하는 자바스크립트 고유의 특징을 호이스팅(hoisting) 이라고 한다.

var

var 키워드로 선언한 변수가 생성되기 전에 참조해도 에러가 발생하지 않고 undefined가 출력된다. 이는 아래 코드처럼 선언과 동시에 값을 할당해주더라도 마찬가지다.

console.log(score); // undefined
var score = 20;
console.log(score); // 20

위 코드가 실제로는 아래처럼 동작한다.

var score; // 호이스팅으로 인해 끌어올려진 선언문
console.log(score); // undefined
var = 20;
console.log(score); // 20

자바스크립트 엔진은 변수 선언을 2단계에 거쳐 수행한다.

  1. 선언 단계: 변수 이름을 등록해서 자바스크립트 엔진에 변수의 존재를 알린다.
  2. 초기화 단계: 값을 저장하기 위한 메모리 공간을 확보하고 암묵적으로 undefined를 할당해 초기화한다.

var 키워드로 생성된 변수는 “선언 단계”“초기화 단계” 가 동시에 진행된다. 따라서 var 키워드로 선언된 변수는 암묵적으로 undefined가 할당되기 때문에 에러가 발생하지 않는다.
변수의 생성 이전에 참조가 가능하다는 점은 오류를 발생 시키지는 않지만 코드의 가독성을 나쁘게 만들 뿐더러 예상치 못한 결과를 야기할 수도 있다. 이러한 이유로 ES6에서 letconst 키워드가 도입되며 var키워드의 사용은 지양되고 있다. 그렇다면 letconst로 생성한 변수에서는 변수 호이스팅이 작동하지 않는 것인가?

let, const

letconst를 사용하더라도 변수 호이스팅은 작동한다. 다만 호이스팅이 발생하지 않는 것"처럼" 동작한다. 아래 코드를 보면 let키워드로 변수를 생성할 경우 변수의 선언문 이전에 변수를 참조하면 ReferenceError(참조 에러)가 출력되는 모습을 확인할 수 있다.

console.log(score); // ReferenceError: score is not defined
let score;
console.log(score); // undefined

letconst 키워드로 선언한 변수는 “선언 단계”와 “초기화 단계”가 분리되어 진행된다. 그리고 두 단계의 사이에 '일시적 사각지대(Temporal Dead Zone: TDZ)' 라는 것이 생긴다.

변수가 선언 단계를 거친 뒤 이 구간에 있을 때 변수에 참조할 경우 ReferenceError가 발생한다. 따라서 위 코드를 실행시키면 실제론 아래 코드처럼 동작한다.

// 호이스팅 발생, 선언 단계
let score;  
// 일시적 사각지대(TDZ) 구간 
console.log(score); // ReferenceError
// 초기화 단계
score = undefined; 
// 참조
console.log(score); // undefined

따라서 score변수가 호이스팅 되었더라도 실제로 변수 선언문을 만나 초기화 되기 전까지는 변수를 참조할 수 없다.

내용을 요약해보자.

var 키워드로 변수를 생성할 경우 선언 단계초기화 단계 가 동시에 일어나기 때문에 변수의 선언문 이전에 해당 변수를 참조하면 undefined가 출력된다.
letconst로 변수를 생성할 경우 선언 단계초기화 단계 사이에 일시적 사각지대(TDZ) 가 있으므로 변수의 선언문 이전에 해당 변수를 참조할 경우 해당 변수는 아직 초기화가 이루어지지 않았기 때문에 ReferenceError가 발생한다.

profile
지속적인 성장

0개의 댓글