ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [코어 자바스크립트 북스터디 2주차] 2장. 실행 컨텍스트
    📝 기록/독서 기록 2021. 11. 25. 22:25

    ✅ 삼색 볼펜법 활용
    빨간색: 핵심내용
    파란색: 핵심은 아니지만 중요하다고 생각되는 내용
    초록색: 흥미로운 내용

    2장 실행 컨텍스트

    실행 컨텍스트: 실행할 코드에 제공할 환경 정보들을 모아놓은 객체

    자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념

    1. 실행 컨텍스트란?

    스택: 출입구가 하나뿐인 깊은 우물 같은 데이터 구조

    개발자들 사이에서 유명한 사이트인 스택오버플로우는 아래와 같은 이유로 네이밍되었다고 생각하면 된다.
    데이터를 100개만 저장할 수 있는 우물에 100개 이상의 데이터를 넣으려고 하면 넘친다(overflow). 많은 프로그래밍 언어들은 이처럼 스택이 넘칠 때 에러를 던진다.

    큐: 양쪽이 모두 열려 있는 파이프

    전체 코드의 환경과 순서
    1. 
    동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성
    2. 콜 스택에 쌓아 올림
    3. 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행

    '동일한 환경': 하나의 실행 컨텍스트를 구성할 수 있는 방법으로, 전역 공간, eval() 함수, 함수 등을 말한다.

    전역 컨텍스트라는 개념은 일반적인 실행 컨텍스트와 특별히 다르지 않다.
    굳이 차이점을 찾자면, 전역 컨텍스트가 관여하는 대상은 함수가 아닌 전역 공간이기 때문에 arguments가 없다.
    전역 공간을 둘러싼 외부 스코프란 존재할 수 없기 때문에 스코프 체인 상에는 전역 스코프 하나만 존재하는 것.

    최상단의 공간은 코드 내부에서 별도의 실행 명령이 없어도 브라우저에서 자동으로 실행하므로 자바스크립트 파일이 열리는 순간 전역 컨텍스트가 활성화된다고 이해하면 된다.

    어떤 실행 컨텍스트가 활성화될 때 자바스크립트 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집해서 실행 컨텍스트 객체에 저장한다.

    저장되는 목록
    - VariableEnvironment: 현재 컨텍스트 내의 식별자들에 대한 정보, 외부 환경 정보, 선언 시점의 LexicalEnvironment의 스냅샷, 변경 사항 반영 X
    - LexicalEnvironment: 처음엔 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영됨
    - ThisBinding: this 식별자가 바라봐야 할 대상 객체

    2. VariableEnvironment

    VariableEnvironment에 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지한다는 점이 다르다.

    초기화 과정 중에는 사실상 완전히 동일하고 이후 코드 진행에 따라 서로 달라지게 된다.

    💡 왜 굳이 VariableEnvironment를 활용하여 스냅샷을 찍어두는 것일까?

    1. 엔진 내부에서 그렇게 구현되어있을분 정확한 사용이유를 알진 못함
    2. with함수를 사용할때 컨텍스트가 확장되면서 사용된다고 함
    (🔗 https://www.inflearn.com/questions/73195)

    3. LexicalEnvironment

    lexical의 뜻은 '사전적인'으로 받아들이면 좀 더 이해하기 쉽다. 
    즉, "현재 컨텍스트 내부에는 a, b, c와 같은 식별자들이 있고 그 외부 정보는 D를 참조하도록 구성돼 있다"라는, 컨텍스트를 구성하는 환경 정보들을 사전에서 접하는 느낌으로 받아 들이면 된다.

    3-1. environmentRecord와 호이스팅

    environmentRecord에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다.

    저장되는 식별자 정보
    1. 컨텍스트를 구성하는 함수에 지정된 매개변수 식별자
    2. 선언한 함수가 있을 경우 그 함수 자체
    3. var로 선언된 변수의 식별자

    컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집한다.

    💡 참고
    전역 실행 컨텍스트는 변수 객체가 아닌 전역 객체를 활용한다.
    전역 객체에는 브라우저의 window, node.js의 global 객체 등이 있다.
    이들은 자바스크립트 내장 객체가 아닌 호스트 객체로 분류된다.

    코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있게 되는 셈.

    호이스팅: 변수 정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념, "끌어올리다"라는 의미.

    호이스팅 규칙

    environmentRecord는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지에만 관심이 있고, 각 식별자에 어떤 값이 할당될 것인지는 관심이 없다.

    함수를 실행하는 순간, 함수의 실행 컨텍스트가 생성된다. 이때 변수명과 함수 선언의 정보를 위로 끌어올린다(수집한다).
    변수는 선언부와 할당부를 나누어 선언부만 끌어올리는 반면 함수 선언은 함수 전체를 끌어올린다.

    함수 선언문과 함수 표현식

    함수 선언문: function 정의부만 존재하고 별도의 할당 명령이 없는 것

    함수 표현식: 정의한 function을 별도의 변수에 할당하는 것
    - 기명 함수 표현식: 함수명을 정의한 함수 표현식
    - 익명 함수 표현식: 함수명을 정의하지 않은 함수 표현식
    일반적으로 함수 표현식: 익명 함수 표현식으로 생각함

    💡 참고
    기명 함수 표현식은 외부에서 함수명으로 함수를 호출할 수 없다. 그럼 왜 사용될까?
    과거의 익명 함수 표현식의 함수명은 undefined 또는 unnamed라는 값이 나왔었다. 이 때문에 기명 함수 표현식이 디버깅 시 어떤 함수인지 추적하기에 익명 함수 표현식보다 유리한 측면이 있었다. 하지만 익명도 이제는 name 프로퍼티가 할당된다.
    그래서 함수 내부에서 재귀함수를 호출하는 용도로 기명 함수를 사용할 듯하지만 굳이 그렇게 사용해야 할 필요가 있을지는..

    함수 선언문은 전체를 호이스팅한 반면 함수 표현식은 변수 선언부만 호이스팅한다. 함수도 하나의 값으로 취급할 수 있다는 것.
    함수를 다른 변수에 값으로써 '할당'한 것이 곧 함수 표현식이다.

    전역 컨텍스트가 활성화될 때 전역 공간에 선언된 함수들이 모두 가장 위로 끌어올려진다.
    동일한 변수명에 서로 다른 값을 할당할 경우, 나중에 할당한 값이 먼저 할당한 값을 덮어씌운다(override).
    따라서 코드를 실행하는 중에 실제로 호출되는 함수는 오직 마지막에 할당한 함수, 즉 맨 마지막에 선언된 함수뿐.
    원활한 협업을 위해서는 전역 공간에 함수를 선언하거나 동명의 함수를 중복 선언하는 경우는 지양해야 한다.

    3-2. 스코프, 스코프 체인, outerEnvironmentReference

    스코프: 식별자에 대한 유효 범위

    스코프 체인: '식별자의 유효범위', 즉 스코프를 안에서부터 바깥으로 차례로 검색해나가는 것

    스코프 체이닝을 가능하게 하는 것이 바로 outerEnvironmentReference이다.

    스코프 체인

    outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.

    outerEnvironmentReference는 연결 리스트(linked list) 형태를 띤다.

    각 outerEnvironmentReferencesms 오직 자신이 선언된 시점의 LexicalEnvironment만 참조하고 있으므로 가장 가까운 요소부터 차례대로만 접근할 수 있고 다른 순서로 접근하는 것은 불가능할 것.

    여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하게 된다.

    스코프 체인 상에 있는 변수라고 해서 무조건 접근 가능한 것은 아니다.

    변수 은닉화: 현재 검색하고 있는 함수 내부에서 이미 선언된 변수가 있다면, 전역 공간에서의 동일한 이름의 변수에는 접근할 수 없는 것

    전역 변수와 지역 변수

    전역 공간에서 선언한 변수는 전역 변수이고, 함수 내부에서 선언한 변수는 무조건 지역변수이다.

    코드의 안전성을 위해 가급적 전역 변수 사용을 최소화하고자 노력해야 한다.

    4. this

    실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장된다.

    실행 컨텍스트의 활성화 당시에 this가 지정되지 않은 경우 this에는 전역 객체가 저장된다.

    그 밖에는 함수를 호출하는 방법에 따라 this에 저장하는 대상이 달라진다.

    2주 차 회고

    오늘은 저번 주랑 달리 컨디션이 좋지 않아서 집중하기가 좀 어려웠는데, 그래도 저번 주보다 독서 시간이 늘어나서 그런지 다행히 시간 안에 다 읽었다. 실행 컨텍스트는 이전에도 블로그 정리하면서도 너무 어려워서 힘들었었는데, 이 책으로 실행 컨텍스트에 대해 뭔가 막연하게만 알고 있던 개념들을 하나둘씩 확실하게 가져갈 수 있었다. 개념이나 어휘들이 익숙해질 때까지 여러 번 더 읽어봐야겠다. 👍