Notice
Recent Posts
Recent Comments
Link
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
Tags more
Archives
Today
Total
관리 메뉴

개발의변화

모던 자바스크립트 23장 실행 컨텍스트 본문

카테고리 없음

모던 자바스크립트 23장 실행 컨텍스트

refindmySapporo 2023. 12. 1. 18:53
반응형

ECMAScript 사양은 소스코드(ECMAScript code)를 4가지 타입으로 구분

  • 전역 코드 : 전역에 존재하는 소스코드 (전역 스코프 생성, 바인딩)
  • 함수 코드: 함수 내부에 존재하는 소스코드 (지역스코프 생성, 지역변수,매개변수,arguments 객체 관리, 스코프 연결)
  • eval 코드: 빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드 (strict mode에서 자신만의 독자적인 스코프 생성)
  • 모듈 코드: 모듈 내부에 존재하는 소스코드 (모듈 스코프 생성)

소스코드의 평가와 실행

소스코드 평가 과정에서는 실행 컨텍스트를 생성하고 변수,함수 등의 선언문 먼저 실행 -> 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프에 등록

그 후 선언문을 제외한 소스코드가 순차적으로 실행 -> 소스코드 실행에 필요한 정보를 실행 컨텍스트가 관리하는 스코프에서 검색 취득
그 후 소스코드의 실행결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록

var x
x = 1

소스코드 평가 과정에서 var x먼저실행 undefined로 초기화
그 후 실행 과정에서 x를 확인하기 위해 실행컨텍스트가 관리하는 스코프에 x변수가 등록되어 있는지 확인 후 값을 할당하고 결과를 실행컨텍스트가 등록관리

// 전역 변수 선언
const x = 1;
const y = 2;

// 함수 정의
function foo(a) {
  // 지역 변수 선언
  const x = 10;
  const y = 20;

  // 메서드 호출
  console.log(a + x + y); // 130
}

// 함수 호출
foo(100);

// 메서드 호출
console.log(x + y); // 3

실행 컨텍스트는 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역

실행 컨텍스트 스택

var x = 1;
const y = 2;

function foo (a) {
  var x = 3;
  const y = 4;

  function bar (b) {
    const z = 5;
    console.log(a + b + x + y + z);
}
  bar(10);
}

foo(20); // 42

실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행 중인 코드의 실행 컨텍스트

렉시컬 환경

식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트

렉시컬 환경은 키와 값을 갖는 객체 형태의 스코프를 생성하여 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리한다.
실행 컨텍스트는 LexicalEnvironment와 VariableEnvironment로 구성

생성 초기: 렉시컬과 베리어블 컴포너트는 하나의 동일한 렉시컬 환경 참조
이후: VariableEnvironment 컴포넌트를 위한 새로운 렉시컬 환경 생성, VariableEnvironment와 LexicalEnvironment 내용이 달라짐

렉시컬 환경

  1. 환경 레코드: 스코프에 포함한 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소다. 환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 있다.

  2. 외부 렉시컬 환경에 대한 참조: 외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킨다. 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 상위 코드의 렉시컬 환경을 말한다.

var x = 1;
const y = 2;

function foo (a) {
  var x = 3;
  const y = 4;

  function bar (b) {
    const z = 5;
    console.log(a + b + x + y + z);
}
  bar(10);
}

foo(20); // 42
  1. 전역 객체 생성
    전역 코드가 평가되기 이전에 생성된다.
    빌트인 전역 프로퍼티와 빌트인 전역 함수, 그리고 표준 빌트인 객체 추가, Web API 또는 특정 환경을 위한 호스트 객체 포함

  2. 전역 코드 평가

전역 실행 컨텍스트 생성

전역 렉시컬 환경 생성 (전역 환경 레코드 생성, 객체 환경 레코드 생성, 선언적 환경 레코드 생성)

전역 렉시컬 환경 생성하고 전역 실행 컨텍스트에 바인딩
렉시컬 환경은 환경레코드, 외부 렉시컬환경에 대한 참조
전역 환경레코드는 전역 스코프 역할하는 객체 환경 레코드(var,빌트인 전역 프로퍼티와 빌트인 전역 함수), 선언적 환경 레코드(const,let)

객체 환경 레코드 생성

전역 코드 평가 과정에서 var 키워드로 선언한 전역 변수와 함수 선언문으로 정의된 전역 함수는 전역 환경 레코드의 객체 환경 레코드에 연결된 BindingObject를 통해 전역 객체의 프로퍼티와 메서드가 된다.

var x = 1;
const y = 2;

function foo (a) {
...

함수 선언문으로 정의한 함수가 평가되면 함수 이름과 동일한 이름의 식별자를 객체 환경 레코드에 바인딩된 BindingObject를 통해 전역 객체에 키로 등록하고 생성된 함수 객체를 즉시 할당

하지만 변수 할당문은 언제나 undefined

선언적 환경 레코드 생성

let,const 키워드로 선언한 전역변수는 선언적 환경 레코드에 등록되고 관리

let,const는 선언 단계와 초기화 단계가 분리되어 진행되어 런타임에 실행 흐름이 변수 선언무에 도달하기 전까지 일시적 사각지대에 빠지게 된다.

let foo = 1; // 전역 변수

{
  // let, const 키워드로 선언한 변수가 호이스팅되지 않는다면 전역 변수를 참조해야 한다.
  // 하지만 let 키워드로 선언한 변수도 여전히 호이스팅이 발생하기 때문에 참조 에러(ReferenceError)가 발생한다.
  console.log(foo); // ReferenceError: Cannot access 'foo' before initialization
  let foo = 2; // 지역 변수
}

this 바인딩

[[GlobalThisValue]] 내부 슬롯에 this가 바인딩
GlobalThisValue 내부 슬롯에 바인딩되어 있는 객체가 전역코드에서 this를 참조하면 실행

외부 렉시컬 환경에 대한 참조 결정

전역 코드는 외부 렉시컬 환경에 대한 참조가 null로 할당되어짐

  1. 전역 코드 실행
    변수 할당문이 실행되어 전역 변수 x,y에 값이 할당

식별자 결정: 어느 스코프의 식별자를 참조하면 되는지 결정하는 방식

var x = 1;
const y = 2;

function foo (a) {
  var x = 3;
  const y = 4;

  function bar (b) {
    const z = 5;
    console.log(a + b + x + y + z);
}
  bar(10);
}

foo(20); // ← 호출 직전

전역 평가에서 foo 함수 코드 평가로 제어권이 이동

  1. 함수 실행 컨텍스트 생성
    foo 함수 실행 컨텍스트 생성 -> 실행 컨텍스트 스택의 최상위로 된다. (실행중인 실행 컨텍스트)
  2. 함수 렉시컬 환경 생성
    foo 함수 렉시컬 환경을 생성하고 foo 함수 실행 컨텍스트 바인딩
  • 2.1 함수 환경 레코드 생성
    매개변수, arguments 객체, 함수 내부에서 선언한 지역 변수와 중첩 함수를 ㅌ등록
  • 2.2 this 바인딩
    ThisValue 내부 슬롯에 this가 바인딩된다.
    함수 호출 방식에 따라 결정된다.
    foo 함수는 일반 함수로 호출되었므로 this는 전역 객체를 가리킨다.
  • 2.3 외부 렉시컬 환경에 대한 참조 결정
    외부 렉시컬 환경에 대한 참조에 foo 함수 정의가 평가된 시점에 실행 중인 실행 컨텍스트의 렉시컬 환경의 참조가 할당된다.
    함수 객체의 내부슬롯 Environment에 함수의 상위 스코프를 저장
  1. foo 함수 코드 실행

식별자 결정ㅇㄹ 위해 실행 중인 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색
검색된 식별자에 값을 바인딩

  1. bar 함수 코드 실행

console.log 식별자 검색 스코프체인의 상위 스코프 전역 레시컬 환경으로 이동하여 console 식별자를 검색

  1. bar 함수 코드 종료

bar가 즉시 소멸 되지 않는다 -> 렉시컬 환경은 실행 컨텍스트에 의해 참조되기는 하지만 독립적인 객체. 누군가에 의해 참조되지 않을 때 가비지컬렉터가 메모리 해제시킴

  1. foo코드 실행 종료

  2. 전역 코드 실행 종료

반응형