ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 클래스 호이스팅
    JavaScript/입 속의 검은 잎 2022. 10. 18. 10:52

    먼저, 클래스는 함수의 일종이다.

     

    클래서 선언문으로 정의한 클래스는 소스코드 평가과정, 즉 런타임 이전에 먼저 평가되어 함수 객체를 생성한다.
    이때 클래스가 평가되어 생성된 함수 객체는 생성자 함수로서 호출할 수 있는 함수, 즉 constructor다.
    생성자 함수로서 호출할 수 있는 함수는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불어 생성된다.
    프로토타입과 생성자 함수는 단독으로 존재할 수 없고, 언제나 쌍으로 존재하기 때문이다.

    <모던자바스크립트 Deep Dive>, 421쪽.

     

    const Jedi = '';
    
    {
    //호이스팅이 발생하지 않는다면 ''이 출력되어야 한다.
    console.log(typeof Jedi) //ReferenceError: Cannot access 'Jedi' before initialization
    
    //클래스 선언문
    class Jedi {}
    }

     

    var, let, const, function, class 등 선언된 모든 식별자는 호이스팅된다.

    모든 선언문은 런타임 이전에 먼저 lexical 환경에 들어오기 때문이다.

     

    다만, 클래스는 var처럼 호이스팅 되지는 않고, let과 const 처럼 호이스팅된다.

    var는 선언단계와 초기화단계가 동시에 이루어진다.

    let과 const는 선언이 lexical 환경에 들어가도, 초기화는 이루어지지 않는다.

    이 선언단계와 초기와 단계 사이에서 TDZ가 발생한다.

     

    클래스도 마찬가지다.

    선언이 lexical  환경에 등록된 것과 초기화 단계의 분리, 그 분리된 틈을 'TDZ'라고들 부른다.

    그리고 TDZ 때문에 호이스팅이 발생하지 않는 것처럼 동작한다.


    TDZ

    //let으로 선언한 변수는 '선언단계'와 '초기화 단계'가 분리되어 진행된다.
    //런타임 이전에는 자바스크립트 엔진에 의해 선언단계가 먼저 실행.
    //초기화 단계는 변수 선언문에 도달했을 떄 실행.
    //초기화 이전에 변수에 접근하려 하면 reference error 발생.
    //let 으로 선언한 변수는 스코프 시작지점부터 초기화 단계 시작지점 까지 변수 참조 할 수 없다.
    
    
    //런타임 이전에 선언단계 실행. 아직 초기화 안됨.
    console.log(bar) //reference error
    
    //선언단계와 초기화 단계의 사이. 이곳을 TDZ라 한다.
    
    let bar; // 초기화단계
    
    console.log(bar) //undefined
    
    bar = 1; // 할당 단계
    
    console.log(bar); // 1

    lexical scope

    var Anakin = "Jedi"
    
    function Sith(){
        var Anakin = "Sith"
        force()
    }
    
    function force(){
        console.log(Anakin);
    }
    
    console.log(Sith()) // Jedi //리턴이 없으니 undefined도 찍힘
    force() // Jedi

    함수가 어디서 호출됐는지에 따라 스코프가 정해진다면

    (aka 동적 스코프 dynamic scope)

    force() 함수의 상위 스코프는 Sith() 함수 지역스코프 & 전역스코프. 

    그렇다면 아마 "Sith" 가 출력되어야 했다.

     

     

    함수를 어디서 정의했는지에 따라 상위 스코프가 정해진다면

    (aka 정적 스코프 static scope, 어휘적 스코프 lexical scope)

    함수가 호출된 위치는 상위 스코프 결정에 아무 영향 없다.

    어디서 정의됐는지에 따라 결정된다.

    따라서 함수의 상위 스코프는 언제나 자신이 정의된 스코프다.

     

    자바스크립트는 렉시컬 스코프를 따른다.

    함수 정의가 실행될 때 스코프는 정적으로 결정된다.

    함수정의에 의해 생성된 함수객체는 이렇게 결정된 상위 스코프를 기억하고, 호출될 때마다 참조한다.

     

    위 예제에서 force()는 전역에서 정의되었다.

    그러므로 코드 실행 전 평가되어 생성된 force 함수의 객체는 자신이 정의된 스코프, 전역 스코프를 기억한다.

    force() 함수는 전역 스코프에서의  Anakin을 기억하고 있따.

    그러므로 Jedi가 두번 출력된다.

    'JavaScript > 입 속의 검은 잎' 카테고리의 다른 글

    클래스, super, 오버라이딩  (0) 2022.10.12
    async/await  (0) 2022.10.05
    promise catch error  (0) 2022.10.05
    try catch error  (1) 2022.10.05
    json 객체  (0) 2022.10.05
Designed by Tistory.