-
Notes from reading 🔖 You Don't Know JS Yet - 10JavaScript 2026. 1. 17. 10:16
### 파트 2 - chapter 5 변수의 비밀 생명주기
- 변수 선언 위치에 따른 작동 방식의 차이와 사용 여부
- 스코프 아래에 있더라도, 스코프 시작 부분에서 변수의 가시성이 확보된다 -> 호이스팅
- function 함수 선언문의 경우 고유 특성인 함수 호이스팅이 있다.
- 함수 선언문으로 함수가 선언되면, 함수 이름에 해당하는 식별자가 스코프 최상단에 선언되고, 함수 참조로 해당 값이 자동 초기화 됨
- 따라서 함수 선언문은 스코프 내 어디서든 호출 가능
- 함수 선언문 및 var를 사용한 선언 변수의 호이스팅 -> 이름 식별자가 블록 스코프가 아니라, 가장 가까운 함수 스코프에 등록됨 (함수 스코프가 없으면 전역 스코프)
- 함수 표현식에서는 함수 호이스팅이 적용되지 않음
- var로 선언한 변수는 호이스팅도 되고 여기에 더해서 스코프가 시작될 때 자동으로 undefined로 초기화 됨 (사용 가능)
- 함수 선언문은 호이스팅되고 함수 참조값으로 초기화까지 다 됨 (=> 함수 호이스팅)
- var는 호이스팅은 되는데, 값 초기화는 안되고 undefined가 일단 들어감
- 함수 표현식 실제 값 할당은 런타임에서 해당 코드가 실행되기 전까지는 일어나지 않음
- 이름 식별자 자체는 선언문, 표현식 모두 호이스팅 됨
- 호이스팅은 코드 재정렬 매커니즘으로 비유할 수 있다. (정확하지는 않음 - 실제로 JS 엔진이 코드 재정렬을 하지는 않기 때문)
- 프로그램이 실제 모든 스코프 경계와 선언문을 찾는 유일한 방법은 파싱
- 함수 호이스팅은 변수 호이스팅보다 우선 순위가 높다.
- 동일한 스코프에서 변수가 두 번 이상 선언 ? -> X
- 동일 스코프에서 같은 이름의 var 변수를 새로 선언한다 해도, 아무런 역할을 하지 않는다.
- let이나 const의 경우 재선언 시 SyntaxError가 발생한다.
- const의 경우는 좀 다른데, 기술적인 이유로 재선언이 불가능
- const는 선언과 함께 값 초기화를 해줘야 하는데, 할당을 생략하면 SyntaxError가 발생한다.
- 재선언 시 재할당이 필요한 구조. (하지만 재할당이 불가능)
- 반복문은 새로운 반복이 시작할 때 마다 새 스코프가 생성됨 (매번 초기화)
- 다만, 반복문 내에서 var 변수를 썼을 때 var는 전역 스코프에 연결되어 초기화되지 않음
- for 반복문의 조건문에 들어가는 변수 및 내부 스코프에 선언된 변수는 각 스코프 인스턴스마다 정확히 한번만 선언된다.
- 일반적으로 for 반복문의 조건문에는 const를 사용하는 것이 안전하지 않다. (재할당이 발생하여 에러)
컴파일러는 var, let, const 선언자를 제거하고 각 스코프 최상단에 해당 식별자를 등록함
- 초기화 되지 않은 변수와 TDZ -> let & const
- let 및 const는 선언 한 뒤 초기화를 하여 사용 가능.
- 스코프에 진입한 후, 변수 자동 초기화가 일어나기 까지의 시간 -> Temporal Dead Zone (TDZ)
- 변수는 존재하지만, 초기화 되지 않아서 접근할 수 없는 시간대를 의미
- var로 선언한 변수는 TDZ 관찰 X let및 const만 관찰 가능하다
/* * ================================================== * Part 2 - Chapter 5 : 변수의 비밀 생명주기 * ================================================== * * 이 파일은 "JS 엔진이 변수를 어떻게 수집하고, * 언제 초기화하고, 언제 사용할 수 있게 만드는지" * 를 한 번에 보여주기 위한 예제다. */ /** * -------------------------------------------------- * [1] 스코프 진입 단계 (컴파일 / 파싱 단계) * * JS 엔진은 코드를 실행하기 전에: * - 모든 스코프 경계를 파악하고 * - var / let / const / function 선언을 수집한다 * * 👉 이 단계에서 '호이스팅'이 발생한 것처럼 보인다 */ /** * [2] 함수 선언문 - 함수 호이스팅 * * - 식별자 선언 O * - 함수 참조로 즉시 초기화 O */ hoistedFunction(); // ✅ 정상 호출 function hoistedFunction() { console.log("I am fully hoisted"); } /** * -------------------------------------------------- * [3] var 변수 호이스팅 * * - 식별자 선언 O * - 초기값 undefined 자동 할당 */ console.log(varVariable); // undefined (에러 아님!) var varVariable = "var value"; console.log(varVariable); // "var value" /** * 내부적으로는 이런 느낌 (개념적 설명) * * var varVariable; * varVariable = undefined; * ... * varVariable = "var value"; */ /** * -------------------------------------------------- * [4] 함수 표현식 * * - 변수 호이스팅은 발생 * - 함수 값 할당은 런타임까지 대기 */ console.log(fnExpression); // undefined // fnExpression(); // ❌ TypeError: fnExpression is not a function var fnExpression = function () { console.log("function expression"); }; fnExpression(); // ✅ 여기서부터 사용 가능 /** * 👉 "이름 식별자"는 호이스팅 됐지만 * 👉 "함수 값"은 아직 없었음 */ /** * -------------------------------------------------- * [5] 함수 호이스팅 vs 변수 호이스팅 우선순위 */ console.log(priority); // function priority() {} function priority() { return "function"; } var priority = "variable"; console.log(priority); // "variable" /** * 정리: * - 함수 선언문이 먼저 등록됨 * - 이후 var 선언은 무시 (같은 이름이면) * - 하지만 var 할당은 런타임에 실행됨 */ /** * -------------------------------------------------- * [6] let / const 와 TDZ (Temporal Dead Zone) */ { // TDZ 시작 지점 // console.log(letValue); // ❌ ReferenceError let letValue = 10; console.log(letValue); // 10 // TDZ 종료 } /** * let / const는: * - 선언은 스코프 진입 시 완료 * - 초기화는 선언문 실행 시점에 발생 * * 👉 그 사이가 TDZ */ /** * var에는 TDZ가 없다 */ { console.log(varValue); // undefined var varValue = 20; } /** * -------------------------------------------------- * [7] 재선언 규칙 */ // var는 같은 스코프에서 재선언 가능 (아무 일도 안 일어남) var a = 1; var a = 2; console.log(a); // 2 // let / const는 재선언 불가 // let b = 1; // let b = 2; // ❌ SyntaxError // const는 선언 + 초기화 필수 // const c; // ❌ SyntaxError const c = 3; // c = 4; // ❌ TypeError /** * const는: * - 재선언 불가 * - 재할당 불가 * * → 그래서 선언 시 초기화가 필수 */ /** * -------------------------------------------------- * [8] 반복문과 스코프 생명주기 */ for (let i = 0; i < 3; i++) { // 매 반복마다 새로운 스코프 setTimeout(() => { console.log("let:", i); }, 0); } // let: 0, 1, 2 for (var j = 0; j < 3; j++) { setTimeout(() => { console.log("var:", j); }, 0); } // var: 3, 3, 3 /** * 이유: * - let i → 반복마다 새 스코프 + 새 바인딩 * - var j → 하나의 함수/전역 스코프 */ /** * for 문의 초기식은 각 스코프 인스턴스마다 * 정확히 한 번만 선언됨 */ // ❌ const는 재할당되므로 부적합 // for (const k = 0; k < 3; k++) {} // SyntaxError /** * -------------------------------------------------- * [9] 컴파일러 관점 정리 (개념) * * JS 엔진은 대충 이런 작업을 함: * * - 스코프 생성 * - var / let / const / function 식별자 수집 * - TDZ 설정 (let / const) * - 실행 단계에서 할당 처리 */ /** * ================================================== * 핵심 요약 * ================================================== * * - 호이스팅은 "코드 재정렬"이 아니라 "선언 수집 결과" * - 함수 선언문은 선언 + 초기화까지 완료 * - var는 undefined로 초기화 * - let / const는 TDZ 존재 * - 반복문은 스코프 인스턴스를 반복 생성 */'JavaScript' 카테고리의 다른 글
Notes from reading 🔖 You Don't Know JS Yet - 9 (0) 2026.01.03 Notes from reading 🔖 You Don't Know JS Yet - 8 (0) 2025.12.27 Notes from reading 🔖 You Don't Know JS Yet - 7 (0) 2025.12.11 JavaScript AbortController 사용법 정리 (0) 2025.10.11 Symbol.for와 Symbol알아보기 (with. 활용 방법) (0) 2025.09.01