티스토리 뷰
var, let, const의 차이를 호이스팅 관점에서 설명합니다.
var, let, const의 호이스팅 차이
호이스팅이란, 자바스크립트에서 변수와 함수 선언이 실행 컨텍스트의 최상단으로 끌어올려지는 현상을 말합니다. 하지만 변수의 선언과 초기화 방식에 따라 접근 가능 여부가 달라지는데요.
var, let, const는 모두 호이스팅되지만, 동작 방식에 차이가 있습니다. 각 선언 방식의 특징과 동작 순서에 대해 정리해 보았습니다.
1. var의 호이스팅
- 호이스팅 O (선언과 초기화가 함께 진행된다.)
- undefined로 초기화
- 선언 전에 접근해도 undefined을 반환할 뿐 오류는 발생하지 않는다.
console.log(a); // undefined
var a = 10;
console.log(a); // 10
위 코드에서 var a = 10;
은 아래처럼 해석됩니다.
var a; // 선언이 먼저 호이스팅 된다.
console.log(a); // undefined (초기화는 나중에 수행된다.)
a = 10; // 값 할당
console.log(a); // 10
2. let의 호이스팅
- 호이스팅 O (선언만 호이스팅, 초기화 X)
- 초기화 전에는 TDZ(Temporal Dead Zone, 일시적 사각지대)에 있다.
- 선언 전에 접근을 하면 ReferenceError가 발생한다.
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;
console.log(b);
위 코드는 아래처럼 해석됩니다.
// 선언은 호이스팅되지만, 초기화 전이라 TDZ에 존재.
let b;
console.log(b); // TDZ로 인해 접근 불가 (ReferenceError)
b = 20;
console.log(b); // 20
3. const의 호이스팅
- 호이스팅 O (선언만 호이스팅, 초기화 X)
- let과 동일하게 TDZ에 존재한다.
- 선언과 초기화가 동시에 이루어져야 한다. (초기값이 필수이다.)
console.log(c); // ReferenceError: Cannot access 'c' before initialization
const c = 30;
console.log(c);
const c; // SyntaxError: Missing initializer in const declaration
c = 30;
위 코드에서 const c;
선언만 하면 오류가 발생합니다. const는 선언과 동시에 초기화가 필요하기 때문이죠.
호이스팅(Hoisting)의 원리와 내부 동작
그럼 왜 이런 차이가 발생하는지 한단계 더 들어가보겠습니다.
자바스크립트 코드는 두 가지 단계를 거쳐 실행됩니다.
1. 코드 실행 전(메모리 생성 단계, 컨텍스트 생성 단계)
이 단계에서는 실행 컨텍스트가 생성되고, 변수, 함수 선언이 메모리에 등록 됩니다. 즉 호이스팅이 발생하는거죠.
2. 코드 실행 단계
이 단계에서 코드가 한 줄씩 실행됩니다. 그리고 변수에 값이 할당되게 됩니다.
var, let, const의 호이스팅 차이는 변수의 메모리 할당 차이에서 비롯됩니다.
1. var 의 동작 순서
console.log(a); // undefined
var a = 10;
console.log(a); // 10
1. var a
가 전역 실행 컨텍스트(Global Execution Context) 의 Variable Environment(변수 환경)에 등록된다.
2. a는 자동으로 undefined로 초기화된다.
3. 코드 실행 단계에서 a = 10;
할당이 실행된다.
즉, var는 선언과 동시에 undefined로 초기화되므로 선언 전에도 접근이 가능합니다.
추가로 var는 함수 스코프를 가지며, 동일한 변수명을 중복 선언할 수 있습니다.
var a = 1; var a = 2; // 문제없이 덮어씌워짐
console.log(a); // 2
2. let 의 동작 순서
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20; console.log(b);
1. let b
가 Lexical Environment(렉시컬 환경)에 등록된다.
2. b는 undefined로 초기화되지 않고, TDZ에 머무른다.
3. 코드 실행 단계에서 b = 20;
실행 시점에 비로소 메모리에 값이 할당된다.
let은 블록 스코프를 가지며, 같은 스코프 내에서 중복 선언이 불가능하다.
let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared
3. const 의 동작 순서
console.log(c); // ReferenceError: Cannot access 'c' before initialization
const c = 30;
console.log(c);
1. const c
가 렉시컬 환경에 등록된다.
2. let과 마찬가지로 TDZ에 위치된다.
3. const는 선언과 동시에 값이 할당되어야 한다.
const d; // SyntaxError: Missing initializer in const declaration
d = 40;
(const는 불변이 아니라 "재할당"이 불가능한 것일 뿐. 객체, 배열은 내부 속성을 변경할 수 있습니다.)
const obj = { name: "Alice" };
obj.name = "Bob"; // 가능
console.log(obj.name); // Bob
표로 정리해보면 다음과 같습니다.
선언 호이스팅 | 초기화 시점 | 선언 전 접근 | 스코프 |
|
var | ✅ (호이스팅됨) | undefined로 초기화 | 가능 (undefined 반환) | 함수 |
let | ✅ (호이스팅됨) | 선언문 실행 시 초기화 | ❌ (TDZ로 인해 ReferenceError) | 블록 |
const | ✅ (호이스팅됨) | 선언문 실행 시 초기화 (즉시 할당 필수) | ❌ (TDZ로 인해 ReferenceError) | 블록 |
실제 코드를 작성할때에는 가급적 let과 const를 사용하여 블록 스코프를 유지하는게 좋습니다.
감사합니다.
'JS | Node.js' 카테고리의 다른 글
[JS] 프로토타입(Prototype) 이해하기 (0) | 2024.03.18 |
---|---|
[JS] 자바스크립트의 변수 복사 (feat. 얕은복사, 깊은복사) (0) | 2024.03.13 |
[JS] 자바스크립트가 데이터를 할당하는 방법 (feat. 불변성, 가변성) (0) | 2024.03.10 |
[JS] 함수형 프로그래밍(FP : Functional Programming) (0) | 2023.11.24 |
[JS]JavaScript와 Node.js (0) | 2023.11.07 |