ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Notes from reading 🔖 You Don't Know JS Yet - 10
    JavaScript 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 존재
     * - 반복문은 스코프 인스턴스를 반복 생성
     */

     

     



Designed by Tistory.