← Dev Log

2023년 06월 20일

·9 min read

오늘 한 일

  • 알고리즘 문제 풀이
  • CS 스터디 - 실행컨텍스트

하루 요약

  • 1시 - 5시까지 학교 도서관에서 공부
  • 그 뒤로 UMC 사람들과 술

Excution Context (실행 컨텍스트)

자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념

즉, 코드들이 실행되기 위한 환경이자 하나의 컨테이너라고 생각하면 된다.

Types of Execution Context

  • Execution Context (EC, 실행 컨텍스트)
    • Global Execution Context (GEC, 전역 실행 컨텍스트)
    • Functional Execution Context (FEC, 함수 실행 컨텍스트)
    • Execution Context inside eval function (Eval 실행 컨텍스트)

Global Execution Context (GEC)

가장 기본적으로 실행되는 컨텍스트

전역 컨텍스트는 자바스크립트 코드가 실행되면 생성된다.

GEC는 단 하나만 존재해야 한다. (JS는 싱글 스레드이기 때문에)

  1. window global object 생성
  2. this에 global object 참조

Functional Execution Context (FEC)

함수가 호출될 때마다 생성

각 함수별로 실행 컨텍스트를 가지고 있지만 실행 컨텍스트는 함수가 호출될 때 만들어진다.

Execution Context Stack (ECS)

실행 컨텍스트가 쌓이는 스택

맨 처음 스택에 쌓이는 컨텍스트는 GEC이다.
코드가 실행되면서 FEC가 생성되면 스택에 쌓이고, 실행이 끝나면 스택에서 제거된다.
모든 js 코드가 실행이 끝나야 GEC가 스택에서 제거된다.

Execution Context 구성

ExecutionContext: {
    LexicalEnvironment: {
        Environment Records,
        Reference to the outer environment,
    },
    VariableEnvironment: {
        Environment Records,
        Reference to the outer environment,
    }
    ThisBinding
}

Lexical Environment & Variable Environment

Variable Environment는 Lexical Environment를 상속하는 관계
Variable Environment과 Lexical Environment 각각 다른 방식으로 선언된 변수들을 관리함

  • Lexical Environment

    • let과 const로 선언된 변수들을 위한 local lexical scope를 단위로 함
    • let, const로 선언된 변수가 메모리에 매핑, 초기값 할당 X
    • 함수선언식으로 선언된 함수가 메모리에 매핑
  • Variable Environment

    • var로 선언된 변수들을 위한 function scope를 단위로 함
    • var로 선언된 변수가 메모리에 매핑, 초기값으로 undefined가 할당

공통된 내부 속성을 알아보자.

Environment Records (환경 레코드)

Environment Record is a specification type used to define the association of Identifiers to specific variables and functions, based upon the lexical nesting structure of ECMAScript code. — ECMAscript

함수와 변수, this, super 등 스코프 내에서 선언된 식별자를 프로퍼티로 저장하는 객체

interface EnvironmentRecord {
  DeclarativeEnvironmentRecord: FunctionEnvironmentRecord & ModuleEnvironmentRecord
  ObjectEnvironmentRecord: ObjectEnvironmentRecord
  GlobalEnvironmentRecord: GlobalEnvironmentRecord
}
  • Declarative Environment Record (선언적 환경 레코드)

    • 스코프 내에서 선언된 식별자를 관리함
    type DeclarativeEnvironmentRecord = {
      HasBinding(N: string): boolean //Determines if an environment record has a binding for the string N.
      CreateMutableBinding(N: string, D: boolean): void //Creates a new mutable binding in an environment record.
      CreateImmutableBinding(N: string, S: boolean): void //Creates a new immutable binding in an environment record.
      InitializeBinding(N: string, V: any): void //Initializes an immutable binding in an environment record.
      SetMutableBinding(N: string, V: any, S: boolean): void //Sets the value of an existing mutable binding in an environment record.
      GetBindingValue(N: string, S: boolean): any //Retrieves the value of an existing binding from an environment record.
      DeleteBinding(N: string): boolean //Removes a binding from an environment record.
      HasThisBinding(): boolean //Determines if an environment record establishes a this binding.
      HasSuperBinding(): boolean //Determines if an environment record establishes a super binding.
      WithBaseObject(): Object //Returns the binding object for environments that provide ThisBinding.
    }
    
    type FunctionEnvironmentRecord = {
      [[ThisValue]]: any //This is the this value used for this invocation of the function.
      [[ThisBindingStatus]]: LexicalEnvironment | initialized | uninitialized //ThisBindingStatus is either lexicalEnvironment, initialized, or uninitialized.
      [[FunctionObject]]: Function //The function object whose invocation caused this Environment Record to be created.
      [[NewTarget]]: Object | undefined //If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.
    
      BindThisValue(V: any): void //Set the [[ThisValue]] and record that it has been initialized.
      GetThisBinding(): any //Return the value of this Environment Record's this binding. Throws a ReferenceError if the this binding has not been initialized.
      GetSuperBase(): Object | undefined //Return the object that is the base for super property accesses bound in this Environment Record. The value undefined indicates that such accesses will produce runtime errors.
    }
    
    type ModuleEnvironmentRecord = {
      CreateImportBinding(N: string, M: Module, N2: string): void //Create an immutable indirect binding in a Module Environment Record. The String value N is the text of the bound name. M is a Module Record, and N2 is a binding that exists in M's Module Environment Record.
      GetThisBinding(): undefined //Return the value of this Environment Record's this binding.
    }
    
  • Object Environment Record (객체 환경 레코드)

    type ObjectEnvironmentRecord = {
      BindingObject: Object //The binding object of this Environment Record.
      isWithEnvironment: boolean //Indicates whether this Environment Record is created for a with statement
    }
    
    • BindingObject(전역 객체)와 연결됨
  • Global Environment Record (전역 환경 레코드)

    • 빌트인 전역 객체, 전역 객체의 프로퍼티 및 스크립트 내의 모든 최상위 선언에 대한 바인딩을 저장함

Reference to the outer environment (외부 환경에 대한 참조)

lexical scope(정적 스코프)를 기준으로 상위 scope의 lexical environment를 참조한다.

각 참조는 단방향 링크드 리스트로 연결되어 있다.

This Binding (this 바인딩)

  • Global Execution Context
    • this는 전역 객체를 참조한다.
  • Functional Execution Context
    • this는 함수를 호출한 객체를 참조한다.
    • arrow function은 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정된다.(상위 스코프의 this를 참조)

🤔 왜 Lexical Environment와 Variable Environment가 분리되어 있을까?

첫 번째 이유 - 스코프

let, const로 선언한 변수들의 경우 스코프가 block scope이다.

var로 선언한 변수들의 경우 스코프가 function scope이다.

만약, 한 함수 안에 여러

Execution Context Phases

  • Phase
    • Creation Phase
    • Execution Phase

Creation Phase

  1. Lexical Environment 생성
  2. Variable Environment 생성
  3. this 바인딩

⚠️ 값이 변수에 할당되지 않고 메모리에 매핑만 되어있는 상태

  • var로 선언된 변수는 undefined로 초기화
  • letconst로 선언된 변수는 초기화 X

Execution Phase

코드를 실행하면서 실제 값이 할당된다.

예시

var a = 3
let b = 4

function func(num) {
  var t = 9
  console.log(a + b + num + t)
}

var r = func(4)
creation phaseexecution phase
// GEC's creation phase
GEC {
	ThisBinding: window,
	LexicalEnvironment: {
		EnvironmentRecord: {
			b: <uninitialized>,
			func: func(){...}
		},
		outer: null
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			a: undefined,
			r: undefined
		},
		outer: null
	}
}
// GEC's execution phase
GEC {
	ThisBinding: window,
	LexicalEnvironment: {
		EnvironmentRecord: {
			b: 4,
			func: func(){...}
		},
		outer 참조: null
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			a: 3,
			r: undefined
		},
		outer 참조: null
	}
}
// func's creation phase
FEC {
	ThisBinding: window,
	LexicalEnvironment: {
		EnvironmentRecord: {
			arguments: { num: 4, length: 1 },
		},
		outer: GECLexicalEnvironment
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			t: undefined
		},
		outer: GECLexicalEnvironment
	}
}
// func's execution phase
FEC {
	ThisBinding: window,
	LexicalEnvironment: {
		EnvironmentRecord: {
			arguments: { num: 4, length: 1 },
		},
		outer: GECLexicalEnvironment
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			t: 9
		},
		outer: GECLexicalEnvironment
	}
}

FEC가 스택에서 제거되고 GEC의 r이 20으로 초기화된다.

GEC {
	ThisBinding: window,
	LexicalEnvironment: {
		EnvironmentRecord: {
			b: 4,
			func: func(){...}
		},
		outer 참조: null
	},
	VariableEnvironment: {
		EnvironmentRecord: {
			a: 3,
			r: 20
		},
		outer 참조: null
	}
}

내일 할 일

  • 알고리즘 문제 풀이
  • CS 스터디 - 실행컨텍스트 ECMAScript 다시 읽고 정리, 브라우저 동작 원리 공부
  • 함수형 프로그래밍 스터디 공부 및 참가
  • 오후 10시 테오 스프린트 1일차