자바스크립트(JS) 엔진의 구성과 동작 원리 (2)

Jin Seok Kim·2022년 11월 4일
0

자바스크립트

목록 보기
2/2

5. 실행 컨텍스트

💡 자바스크립트 코드가 실행되기 위한 정보들을 가진 공간(객체)을 의미하는 추상적 개념

  • 변수 : 지역변수, 전역변수, 매개변수, 객체의 프로퍼티
  • 함수 선언
  • 변수의 유효범위(스코프)
  • this

1) 실행 컨텍스트의 종류

(1) 전역 컨텍스트(Global Execution Context)

기본 실행 컨텍스트로, 함수 내부에 없는 코드는 이 전역 컨텍스트에서 실행된다.

  • script 요소를 처음 만나는 시점에, 전역 컨텍스트를 생성하고 콜스택에 push한다
  1. window 전역 객체를 생성한다
  2. this를 전역 객체로 설정한다

(2) 함수 컨텍스트(Functional Execution Context)

함수가 호출될 때마다 해당 함수에 대한 새로운 컨텍스트가 생성된다.

  • 새로운 함수 컨텍스트가 생성될 때마다 차례대로 수행한다

(3) Eval 컨텍스트(Eval Execution Context)

eval 함수 내에서 생성되는 실행 컨텍스트이다

2) 실행 컨텍스트의 구성

(1) 렉시컬/변수 환경 컴포넌트 (Lexical/Variable Environment Component)

실행 가능한 코드를 실행하기 위한 정보들을 모아둔 곳

  1. 환경 레코드 (Environment Record)

    : 유효 범위(Scope) 안에 있는 식별자와 결과값이 Key Pair로 저장하는 공간

    • 이 환경 레코드는 생성 단계에서는 현재 실행될 컨텍스트의 식별자 정보만을 우선적으로 수집하고, 할당 과정은 실행 단계에 진행된다 (아래 추가 설명)
    • ⭐️ 코드 실행 이전에, 자바스크립트 엔진이 이미 컨텍스트 내의 변수명을 알 수 있는 호이스팅이 가능해지는 원리
    • 환경 레코드는 구성 요소에 따라 3가지로 분류된다
      • 1) 선언적 환경 레코드 : 컨텍스트 내부에서 선언된 변수와 함수, catch 문의 식별자와 실행 결과를 Key Pair로 저장
      • 2) 객체 환경 레코드 : 컨텍스트 외부에 별도로 저장된 데이터를 참조할 때, 해당 레코드의 bindObject 프로퍼티에 저장해 사용한다
        • with
      • 3) 전역 환경 레코드
  2. 외부 렉시컬 환경 참조 (Outer Lexical Environment Reference)

    : 해당 함수를 둘러싸고 있는 외부 영역에 대한 참조를 연결리스트로 관리하는 곳

    • ⭐️ 현재 호출된 함수가 선언된 시점의 Lexical Environment를 참조하는 포인터로 스코프 체인을 가능하게 한다.
    • [[scopes]] 프로퍼티에 해당하는 정보

스코프

💡 식별자에 대한 유효범위를 뜻한다.

  • 전역 스코프와 지역 스코프로 구분되며, 전역 스코프에 선언된 변수는 어디에서든 접근 가능한 반면, 지역 스코프는 선언된 함수의 내부에서만 가능하다.

  • 스코프체인이란 식별자의 유효범위를 찾아 지역 스코프에서 외부 렉시컬 환경 참조를 이용해 상위 스코프를 탐색해 나가는 과정을 말한다.

🤔 렉시컬 환경 컴포넌트 vs 변수 환경 컴포넌트

💡 렉시컬 환경 컴포넌트

  • 변경 사항이 실시간으로 반영된다
  • 따라서 일반적으로 함수의 로컬 스코프 범위를 뜻한다
  • 함수 선언과 변수 바인딩(let, const)을 저장

💡 변수 환경 컴포넌트

  • 선언 시점의 렉시컬 환경 컴포넌트 정보 (식별자 정보, 외부 환경 정보)의 스냅샷
  • 변경 사항을 반영하지 않는다
  • 변수 var 로 선언된 변수를 저장

(2) ThisBinding

this 값의 할당을 결정한다.

  • 전역 컨텍스트 : 전역 객체(window)
  • 함수 컨텍스트 : 호출 형태에 따라 3가지로 분리된다. (TODO: 추후 업데이트)

3) 실행 컨텍스트 생성 과정

💡 자바스크립트 엔진이 실행 컨텍스트를 생성하는 과정을 알아본다
let a = 20;
const b = 30;
var c;

function multiply(e, f){
	var g = 20;
	return e * f * g;
}
c = multiply(20, 30);

(1) 생성 단계 (Creation Phase)

렉시컬 환경 컴포넌트변수 환경 컴포넌트를 생성한다.

  • 렉시컬 환경 컴포넌트 → 함수, let, const
  • 변수 환경 컴포넌트var
GlobalExecutionContext = {
	LexicalEnvironment: {
		EnvironmentRecord: {
			Type: "Object",
			//Identifier bindings go here
			a: < uninitialized >, // 1. 선언 완료 // 초기화는 X
			b: < uninitialized >, // 1. 선언 완료 // 초기화는 X
			multiply: < func >
		}
		outer: <null>
		ThisBinding: <Global Object>
	},
	
	VariableEnvironment: {
		EnvironmentRecord: {
			Type: "Object",
			// Identifier bindings go here
			c: undefined, // 1. 선언 & 초기화 동시에 진행 완료
		}
		outer: <null>
		ThisBinding: <Global object>
	}
}

(2) 실행 단계 (Execution Phase)

모든 변수에 대한 값 할당을 완료하고 코드를 실행한다

GlobalExecutionContext = {
	LexicalEnvironment: {
		EnvironmentRecord: {
			Type: "Object",
			//Identifier bindings go here
			a: 20,
			b: 30,
			multiply: < func >
		}
		outer: <null>
		ThisBinding: <Global Object>
	},
	
	VariableEnvironment: {
		EnvironmentRecord: {
			Type: "Object",
			// Identifier bindings go here
			c: undefined,
		}
		outer: <null>
		ThisBinding: <Global object>
	}
}
  • 새로운 함수 실행 컨텍스트가 생성된다
FUnctionExecutionContext = {
	LexicalEnvironment: {
		EnvironmentRecord: {
			Type: "Declarative",
			//Identifier bindings go here
			Arguments: {0: 20, 1: 30, length: 2},
		},
		outer: <GlobalLexicalEnvironment>,
		ThisBinding: <Global Object or undefined>,
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			Type: "Declarative",
			//Identifier bindings go here
			g: undefined
		},
		outer: <GlobalLexicalEnvironment>,
		ThisBinding: <Global Object or undefined>
	}
}
  • 함수 내부의 변수들에 할당하는 실행단계를 거친다
FUnctionExecutionContext = {
	LexicalEnvironment: {
		EnvironmentRecord: {
			Type: "Declarative",
			//Identifier bindings go here
			Arguments: {0: 20, 1: 30, length: 2},
		},
		outer: <GlobalLexicalEnvironment>,
		ThisBinding: <Global Object or undefined>,
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			Type: "Declarative",
			//Identifier bindings go here
			g: 20
		},
		outer: <GlobalLexicalEnvironment>,
		ThisBinding: <Global Object or undefined>
	}
}

Reference


https://curryyou.tistory.com/237

https://jsyovo.tistory.com/40?category=942594

https://samslow.github.io/development/2020/07/06/JIT/


https://velog.io/@namezin/javascript-동작-원리

https://blog.toycrane.xyz/진짜-쉽게-알아보는-자바스크립트-동작-원리-c7fbdc44cc97

https://tristy.tistory.com/51

profile
블로그 자료 마이그레이션 중입니다

0개의 댓글