관리 메뉴

개발 여행자, 현

[JS] 변수 호이스팅에 대하여 (var, let 차이점) 본문

JavaScript

[JS] 변수 호이스팅에 대하여 (var, let 차이점)

예스현 2023. 8. 3. 11:57

1. var 


var 키워드가 호이스팅이 된다는 것은 이해했지만, (이전 작성했던 글)
let과 const 키워드도 호이스팅이 된다는 것을 완전히 이해하지는 못했었다.

이번에 헷갈렸던 이론을 탐구해보고자 글을 작성한다. 

 

var 키워드로 변수를 선언하면 변수 호이스팅에 의해 변수 선언문이 스코프의 선두로 끌어 올려진 것처럼 동작한다.

즉, 변수 호이스팅에 의해 var 키워드로 선언한 변수는 변수 선언문 이전에 참조가 가능하다.

console.log(abc); // undefined

abc = '123';

console.log(abc); // 123

var abc;

단, 할당문 이전에 변수를 참조하면 언제나 undefined를 반환하는 것에 유의해야 한다.

하지만 변수 선언문 이전에 변수를 참조하는 것은 가독성을 떨어트리고 오류를 발생시킬 여지가 충분하다.

 

2. let


ES6 이후에 var 키워드의 단점을 보완하기 위해 let과 const를 도입했다.

 

let의 특징은 다음과 같다.

 

1) 변수 중복 선언 금지


var a = 123;

var a = 456;

let c = 123;

let c = 456; // SyntaxError

 

2) 블록 레벨 스코프


let a = 1;

{
  let a = 2;
  let b = 3;
}

console.log(a); // 1
console.log(b); // ReferenceError

 

함수의 코드 블록만을 지역스코프로 인정하는 함수 레벨 스코프 var 키워드와는 달리

let 키워드로 선언한 변수는 모든 크도블록을 지역스코프로 인정하는 블록 레벨 스코프를 따른다.

 

따라서 위 예제의 코드 블록 내에서 선언된 a 변수와 b 변수는 지역변수이다.

전역에서 선언된 a 변수와 코드 블록 내의 a 변수는 서로 다른 변수이다. 

 

마찬가지로 b 변수도 지역변수이므로 전역에서 b 변수를 참조할 수 없다.

 

3) 호이스팅


let 키워드로 선언한 변수는 호이스팅이 발생하지 않는 것처럼 동작한다.

console.log(a); // ReferenceError
let a;

이처럼 let 키워드로 선언한 변수를 선언문 이전에 참조하면 참조에러(ReferenceError)가 발생한다.

console.log(a); // undefined

var a;
console.log(a); // undefined

a = 1;
console.log(a); // 1

변수 선언에서 살펴본 바와 같이 var 키워드로 선언한 변수는 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로

'선언단계'와 '초기화 단계'가 한 번에 진행된다.

 

따라서 변수 선언문 이전에 변수에 접근해도 에러가 발생하지 않고 undefined를 반환한다.

 

var 키워드 생명주기

 

하지만 let 키워드로 선언한 변수는 '선언단계'와 '초기화단계'가 분리되어 진행된다.

즉, 런타임 이전에 자바스크립트 엔진에 의해 암묵적으로 선언 단계가 먼저 실행되지만, 초기화 단계는 변수 선언문에 도달했을 때 실행된다.

 

let 키워드로 선언한 변수는 스코프의 시작 지점부터 변수 선언문까지(초기화 단계 시작 지점) 변수를 참조할 수 없다.

스코프의 시작 지점부터 초기화 시작 지점까지 변수를 참조할 수 없는 구간을 '일시적 사각지대(TDZ)'라고 부른다.

 

console.log(a); // ReferenceError

let a;
console.log(a); // undefined

a = 1;
console.log(a); // 1

let 키워드 생명주기

 

let 키워드로 선언한 변수는 변수 호이스팅이 발생하지 않는 것처럼 보인다. 하지만 그렇지 않다 (중요!)

 

let a = 1;

{
  console.log(a); // ReferenceError
  let a = 2;
}

 

만약 호이스팅이 발생하지 않았다면, 전역 변수인 a의 값인 1을 출력했어야 한다.

하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 때문에 참조 에러(ReferenceError)가 발생한다.

 

자바스크립트는 ES6에서 도입된 let, const를 포함해서 모든 선언(var, let, const, function, class 등)을 호이스팅한다. 

단, ES6에서 도입된 let, const, class를 사용한 선언문은 호이스팅이 발생하지 않는 것처럼 동작한다.

 

 

해당 글은 [모던 자바스크립트 Deep Dive - 저자 이응모] 도서의 내용을 참고했습니다.