Javascript] 실행 컨텍스트

Song-Minhyung·2022년 5월 28일

Javascript

목록 보기
2/8
post-thumbnail

실행 컨텍스트란?

실행 컨텍스트의 영어 원문은 Execution Context다.이걸 직역하면 실행 문맥이다.
그리고 자바스크립트에서 가장 중요한 개념이라고도 할 수 있다.

실행 컨텍스트는 실행항 코드에 제공할 환경 정보들을 모아놓은 객체다.
😀 Execution Context = E.C

더 자세히 설명하면 실행 컨텍스트는 전역공간 eval() 함수 가 실행될 때 활성화된다.
활성화된 실행 컨텍스트는 순서대로 콜스택에 쌓이게 된다.

전역공간은 자동으로 생성되고 'eval is evil' 라 불리는 eval 함수를 제외하면
보통의 경우엔 함수를 실행할 때 콜스택에 실행 컨텍스트가 쌓인다고 생각하면 된다.

var a = 1;
function first() {
  function second() {
    console.log(a);	//undifined
    var a = 2;
  }
  second();
  console.log(a):	//1
}
first();
console.log();		//1

위 코드를 실행하면 스택은 아래처럼 쌓인다

12345
second()
first()first()first()
전역 컨텍스트전역컨텍스트전역컨텍스트전역컨텍스트전역컨텍스트

함수가 실행되는 순서로 콜스택에 실행 컨텍스트가 쌓이는걸 볼 수 있다.
스택을 보면 더이상 쌓일 스택이 없으면 맨 위의 코드가 실행된 후 없어진다.


렉시컬 환경

E.C 는 VariableEnvironment Lexical Environment ThisBinding 으로 이뤄져있다.

Variable Environment

😀 Variable Environment = V.E

  • V.E 에 기록된 값들은 절대 변하지 않는다(최초의 스냅샷)

  • V.E 는 두가지 프로퍼티로 구성되어있다.

    • EnvironmentRecord: 식별자, 함수 선언식의 function들
    • OuterEnvironmentReferentce: 선언될 때의 컨텍스트 정보(Lexical Environment)

Lexical Environment

😀 Lexical Environment = L.E

  • L.E V.E는 처음 생성될 동일한 렉시컬 환경을 참조한다.
  • L.E는 코드가 실행됨에 따라 그 값이 변할 수 있다.
    with 혹은 catch문, 블록코드를 사용할 때 그 값이 바뀔 수 있다.

만약 함수 안에 블록스코프가 있다면?

  • 블록 스코프의 E.C는 생성하지 않은 채 상위의 E.C를 그대로 쓴다.
  • L.E를 별도로 생성하여 상위 E.C가 기존의
    L.E 대신 새로 생성한 L.E 바라보도록 한다.
  • 그 후 블록 스코프가 종료되면 원래의 L.E 복구한다.

참고: https://262.ecma-international.org/6.0/#sec-block-runtime-semantics-evaluation

호이스팅

위와같이 L.E에 변수와 함수등을 저장하는 과정 때문에 호이스팅이 발생된다.
여기에 es5, es6의 차이가 있다.

var a = 1;
let b = 2;

{
  console.log(a);// undifined
  console.log(b);// b가 초기화 되기 이전이라는 에러 발생
  var a = 3;	
  let b = 4;  	
  console.log(a);// 3
  console.log(b);// 4
}
console.log(a);	// 3
console.log(b);	// 2

처음에 공부하기 전에는 다른 언어와 마찬가지로 1, 2, 3, 4, 1, 2가 출력될줄 알았다.
하지만 아니었다.

es5에서 var 타입으로 변수를 선언하면
L.E 에 식별자를 수집하는 과정에서 변수를 undifined로 초기화 해버린다.
그래서 변수 선언부 위에서 호출을 하면 undifined가 출력돼버린다.

es6에서 let, const 타입을 변수를 선언한다면
L.E 에 식별자만 수집하고 초기화를 하지 않는다.
그래서 변수의 선언부 위에서 호출하면 아직 초기화되지 않은 변수라는 에러가 발생한다.
이를 Temporal dead zone(TDZ)라 부른다.

함수의 경우는 함수 선언문이냐, 함수 표현식이냐에 따라 결과가 달라진다

함수 선언문

함수 선언문은 아래와 같다.

Func();		// true
function Func() {
  return true;
}
Func();		// true

호이스팅이 일어날 때 변수와 다르게 함수 선언문으로 초기화한 함수는
선언, 초기화 부분이 함께 호이스팅된다.
그래서 코드 어디서든 함수 호출이 가능하다.

함수 표현식

함수 표현식은 아래와 같다.

func();		// func 함수가 초기화 되기 이전이라는 에러 발생
const func = function () {
	return true;
};
func();		// true

함수 선언문과 다르게 함수 표현식은 함수의 선언부만 호이스팅이 된다.
위 함수의 겨우 func만 E.V 에서 수집을 했기때문에 에러가 발생했다.


스코프

스코프란 식별자의 유효범위다.

const a = 1;
function func() {
  const b = 2;
  console.log(a);// 1
}
func();
console.log(b);	// b를 찾을 수 없다는 에러 발생

func 함수에 의해 스코프가 생성됐다.
스코프 내부의 변수는 외부에서는 접근이 불가능하다.
하지만 외부의 변수는 내부에서 접근이 가능하다.

es5에는 함수 스코프만 존재했다. 그래서 함수로만 스코프 생성이 가능했었따.
하지만 es6에선 let, const 변수에 의해 블록 스코프 생성이 가능해졌다.

이렇게 스코프가 생성될 때 마다 L.E는 outerEnvironmentReference를 수집한다.

스코프체인

스코프 체인이란 L.E의 outerEnvironmentReference가 연결된 형태를 말한다.
outerEnvironmentRererence란 호출된 함수가 선언 됐을 때의 L.E를 참조한다.
A함수 안에 B함수 안에 C함수를 선언하게 된다면 스코프 체인은C -> B -> A -> global 형태를 보인다.

만약 C 함수 안에서 a라는 변수를 찾는데 존재하지 않으면 B를 찾아본다.
없으면 A를, 또 없으면 global을 찾아보고 존재한다면 해당 변수를 반환한다.
만약global에도 없다면 undifined를 반환한다.


마무리

  • 실행 컨텍스트는 자바스크립트에서 제일 중요한 핵심 개념이다.
  • 실행 컨텍스트는 LexicalEnvironment, VariableEnvironment, ThisBinding을 프로퍼티로 가진다.
    • L.E와 V.E는 생성될 때 같은 L.E를 바라본다.
    • L.E는 EnvironmentRecord, OuterEnvironmentReference를 프로퍼티로 가진다.
      • EnvironmentRecord는 현재 환경의 정보들을 수집한다.(매개변수, 변수, 함수등)
      • OuterEnvironmentReference는 환경이 구성될 당시의 L.E를 카리킨다.
    • ThisBinding은 상황에 따라 This의 값이 달라지는데, 지정하지 않을경우 global이 지정된다.
  • 자바스크립트는 L.E를 생성할 때 호이스팅이 발생한다.
    • 이로인해 var 변수는 undifined로 초기화, 함수 선언문은 초기화부분과 함께 EnvironmentRecord의 프로퍼티로 지정된다.
    • let, const 변수는 undifined로 초기화 되지 않는다. 그래서 사용도 불가능한데 이 지점을 TDZ Temporal Dead Zone (일시 사각지대)라 한다.
    • 함수 혹은 블록을 만나면 L.E 가 생성되는데 그 L.E의 OuterEnvironmentReference가 연결돼서 스코프 체인을 형성하게 된다.

profile
기록하는 블로그

0개의 댓글