ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 실행컨텍스트, 호이스팅, 스코프체이닝 (feat. 테코톡 하루님)
    CS지식 2023. 11. 4. 15:29

    실행컨텍스트, 호이스팅, 스코프체이닝을 완벽하게 이해하고 싶은데
    호이스팅, 생성 단계, 실행 단계, 선언, 초기화, 일시적 사각지대, 함수 표현식, 함수 선언문, 식별자 결정, 스코프 체인, 스코프 체이닝 등의 여러 개념들이 얽혀있어서 정리가 잘 안됐다.

     

    그런데 테코톡에서 하루님께서 실행컨텍스트를 발표해주신 영상을 보고 속이 시원할정도로 이해가 쏙쏙 잘됐다. 너무 감사했다..ㅠㅠ
    그래서 이 영상을 보며 개념을 정리해보았다!

    https://youtu.be/EWfujNzSUmw?si=ICfUnYVPczB2HqTh


    실행컨텍스트에는 Record가 있고 Outer가 있다. 이를 먼저 이해하면 최종적으로 실행컨텍스트를 더욱 이해할 수 있다!

    1. Record로 JS 호이스팅 이해하기

    

    이처럼 첫 콘솔을 보면 undefined가 찍히는데, 
    선언 라인 전에도 에러가 나지 않고 변수를 참조할 수 있는 현상을 '호이스팅'이라고 한다.

    왜 이렇게 선언문이 마치 최상단에 끌어올려진 듯한 호이스팅 현상이 발생하는 것일까?

    자바스크립트 엔진이 먼저 전체 코드를 스캔하면서 변수같은 정보를 실행컨텍스트의 'Record'에 미리 기록해놓기 때문이다.

     

    - Record = Environment Record = 환경레코드

    식별자와 식별자에 바인딩된 값을 기록해두는 객체이다.

    다시 호이스팅으로 돌아가보자.

    호이스팅에는

    생성단계: 실행컨텍스트를 생성하고 선언문만 먼저 실행해서 환경레코드에 미리 기록해두는 단계,

    실행단계: 선언문 외 나머지 코드 순차적으로 실행해서 환경레코드를 참조하거나 업데이트하는 단계가 있고

    종류가 두가지가 있다.

    호이스팅의 종류

    1.  변수 호이스팅 : var VS const, let

    < var >
    - 1. 생성단계 : 선언과 초기화가 동시에 이루어진다.

    var는 생선단계에서 실행컨텍스트를 생성하고 환경레코드에 undefined로 초기화도 같이한다. 

    - 2. 실행단계

    코드 순차적으로 실행해서 TVChannel을 만나면 환경레코드 값을 업데이트 시켜준다. 



    < const, let > 
    - 1. 생성단계 : 선언만하고 초기화는 하지 않는다. 

    TVChannel 식별자를 기록해두긴 하지만 값을 초기화하지는 않는다. 따라서 선언문 이전에 TVChannel를 참조하려고 하면 Reference Error가 발생한다.


    let, const로 선언한 식별자는 선언 라인 이전에 참조할 수 없는데, 이 구역을 ‘일시적 사각지대’라고 부른다.


     

    - var와 let, const의 차이

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

    let, const는 선언만하고 초기화는 하지 않는다. 그래서 선언 라인 전에는 변수를 참조할 수 없다.
    이는 자바스크립트도 선언 라인 이전에는 변수를 참조할 수 없다는 일반적인 프로그래밍 방식을 추구할 수 있도록
    언어 차원에서 보완된 것이다.

     

    2.  함수 호이스팅 : 함수 표현식(var VS const, let), 함수 선언식

    - 함수 표현식 : 함수를 변수에 담을 수 있다. 변수 호이스팅과 동일하게 동작한다.

    < var >


    선언문 이전에 실행하려고 하면 환경레코드에 기록되어있는 값은 undefined이고 undefined라는 데이터타입은 함수와 달리 호출될 수 없기 때문에 타입 에러가 발생한다.
    < const, let >


    아직 환경레코드에 기록된 값이 없어 Reference Error가 발생한다.


     

    - 함수 선언문

    선언과 동시에 함수가 생성되어 선언 전에도 함수를 사용할 수 있다.

    선언과 동시에 완성된 함수 객체를 생성해서 환경레코드에 기록해둔다. 함수가 에러없이 실행된다.

    그래서 사용을 지양해야한다!!!

     

    - 함수 표현식과 함수 선언문의 차이점

     

    1. 함수 표현식은 var 키워드 일 때는 환경레코드의 값을 undefined로 초기화해두는데 undefined를 호출하려해서 Type Error가 나고, let&const 일 때는 환경레코드에 값을 초기화해두지는 않아서 참조하려니까 Reference Error가 난다. 

     

    2. 함수 선언문은 함수 선언문은 선언과 동시에 함수 생성을 마치고 온전히 환경레코드에 저장해두기 때문에 선언 라인 전에도 함수를 호출할 수 있다.

    2. Outer로 JS 스코프체이닝 이해하기

    - outer

    outer는 외부 환경을 참조할 수 있게 해준다.

     

    이 흐름을 이해해보자.

    1. 함수선언문이라 선언하는 동시에 환경레코드에 생성된 함수가 통째로 기록되고 

    2. 이 함수(goTo2F)를 실행하면 새로운 실행 컨텍스트가 생성된다.

    3. goTo2F 함수의 lamp = true 를 기록한다. 그리고 lamp의 값을 출력하려고 환경레코드를 보니, 불이 꺼진 lamp와 불이 켜진 lamp가 두개가 있다. 자바스크립트 엔진은 둘 중 뭘로 결정해야하나 고민에 빠진다. 이런 상황에서 변수나 함수의 값을 결정해내는 것을 ‘식별자 결정’이라고 한다.

    4. 콜스택 안에 동일한 식별자가 여럿일 때, 자바스크립트 엔진이 어떻게 outer를 활용해서 의사결정을 할까?

    1. goTo2F 함수가 호출되는 시점으로 돌아가보자.

    다시 goTo2F 함수가 호출되는 시점으로 돌아가보면, 함수의 실행 컨텍스트를 새로 생성하고, 이때 새로 생성된 실행 컨텍스트에 바깥 렉시컬 환경으로 돌아갈 수 있는 outer를 남겨놓는다. 이제 필요한 경우에 이전 실행 컨텍스트의 환경레코드에 저장된 식별자도 참조할 수 있게되었다.

     

    2. goTo2F 함수가 실행됨

    lamp를 기록하고 goTo3F 함수가 기록되고

     

    3. goTo2F 함수 안에서 다시 goTo3F 함수가 호출된다. 

    또 실행컨텍스트가 새로 생성되고, 이전 렉시컬환경을 가리키는 outer를 현재의 실행컨텍스트에 저장한다.

     

    4. goTo3F 함수를 실행한다.

    3층에서 pet을 할당하고 원칙적으로 현재 활성화된 실행컨텍스트의 환경레코드를 먼저 보고
    pet의 값이 puppy니까 puppy를 잘 출력해낸다.

     

    5. goTo3F 함수의 lamp를 찾으려고 한다.

    현재 활성화된 실행컨텍스트에는 lamp가 없어서 outer가 가리키는 바깥 렉시컬 환경으로 가서 lamp를 찾아서 값을 출력해낸다.

    이미 2층에서 lamp로 찾아서 1층으로 내려가지 않는다.
    이렇게 동일한 식별자로 인해 상위 스코프에서 선언된 식별자의 값이 가려지는 현상을 ‘변수 섀도잉’이라고 한다.

     

    층층히 실행 컨텍스트가 쌓여있을 때, 현재 활성화된 실행 컨텍스트는 오직 하나이지만, 이전 렉시컬 환경을 가리키는 outer로 타고타고 갈 수 있다.
    이렇게 식별자를 결정할 때 활용하는 스코프들의 연결리스트를 ‘스코프 체인’이라고 한다.
    식별자를 결정하기 위해 타고타고 가서 찾는 과정 자체를 ‘스코프체이닝’이라고 한다.

     

    3. 실행컨텍스트

     실행하는데 필요한 환경을 제공하는 객체이다. 여기서 환경이란 코드 실행에 영향을 주는 조건이나 상태를 의미한다.
    즉, 코드를 실행하는데 필요한 조건이나 상태를 모아둔 객체 바로 실행컨텍스트이다.

     

    자바스크립트 엔진은 실행컨텍스트만 보고도 값을 잘 결정해냈다.
    만약 자바스크립트 엔진이 lamp와 같은 식별자의 값을 정할 때마다 실행컨텍스트 외에 바깥의 다른 메모리를 참조해야 했다면 자바스크립트 엔진의 퍼포먼스는 지금보다 떨어졌을거다!

     

    즉, 실행컨텍스트는 식별자 결정을 더욱 효율적으로 하기 위한 수단으로, 필요한 정보를 한데 모아 제공하는 객체이다.

     

     

    댓글

Designed by Tistory.