JS의 실행 컨텍스트(Execution Context)

zaman·2022년 9월 21일
0

Javascript | Basics

목록 보기
8/8
post-thumbnail

실행 컨텍스트?

자바스크립트 엔진이 코드를 실행하기 위해선 여러 정보들이 필요
예) 전역/매개 변수, 변수의 유효 범위, this같은 정보들

실행 컨텍스트가 활성화되면

  • 호이스팅 발생
  • 외부 환경 정보 구성
  • this 값 결정

JS엔진은 컨텍스트 코드를 실행하는데 필요한 환경 정보들을 수집, 실행 컨텍스트에 저장
→ 코드를 실행하는데 필요한 환경을 제공하는 객체

예시)

var x = 'xxx'; // 전역

function foo () { // outer 컨텍스트
  var y = 'yyy';

  function bar () { // inner 컨텍스트
    var z = 'zzz';
    console.log(x + y + z);
  }
  
  bar();
}

foo();


스택 구조를 가졌기 때문에 가장 위의 실행 컨텍스트가 활성화 됨

1. 프로그램 실행(전역 컨텍스트)
전역 컨텍스트가 콜스택에 담김(전역 컨텍스트는 브라우저를 닫거나 페이지를 떠날 때까지 유지)
2. foo() 함수 실행
foo() 함수에 대한 환경 정보를 수집, 새로운 실행 컨텍스트를 생성하고 전역 컨텍스트 위에 쌓임
3. foo() 함수 실행 중 내부함수 bar()함수 실행
bar() 함수에 대한 환경 정보를 수집, 새로운 실행 컨텍스트를 생성하고 전역 컨텍스트 위에 쌓임
4. bar() 함수가 먼저 실행 종료
bar()의 실행 컨텍스트가 콜스택에서 제거
5. foo() 함수 실행 종료
foo()의 실행 컨텍스트가 콜스택에서 제거

1. 실행 컨텍스트의 구성

1. VariableEnvironment

  • 현재 컨텍스트 내에 식별자(변수)에 대한 정보
  • 외부 환경 정보
  • 선언 시점의 LexicalEnvironment의 스냅샷(변경사항은 반영 ㄴㄴ)

2. LexicalEnvironment

  • 처음에는 VariableEnvironment와 같음
  • 변경사항이 실시간으로 반영

3. ThisBinding

  • this 식별자가 바라보고 있는 대상 객체

공통점
VariableEnvironment, LexicalEnvironment 모두 컨텍스트 내에 변수에 대한 정보를 담고 있음 → 실행 컨텍스트 생성시 VariableEnvironment에 정보를 먼저 담고 이를 복사해서 LexicalEnvironment를 만들기 때문
차이점
VariableEnvironment: 최초 실행 시점의 스냅샷 유지
LexicalEnvironment: 변경사항 업데이트

일반적으로 함수의 LexicalEnvironment는 해당 함수가 가지는 자신의 로컬 스코프 범위를 뜻함

2. EnvironmentRecord & OuterEnvironmentReference

  1. OuterEnvironmentReference
    : 호출된 함수가 선언될 당시 LexicaEnvironment를 참조하는 포인터, 스코프체인(변수 호출시 상위에서 찾을 수 있게 주소 참조)을 가능케함
  2. EnvironmentRecord
    : 컨텍스트에서 선언된 변수, 식별자 정보(식별자, 식별자에 바인딩 된 값 등)
    들이 저장

2-1. 호이스팅(feat, 환경 레코드)

호이스팅
: 선언 라인 전에도 변수를 참조할 수 있는 현상으로 마치 선언문이 최상단에 끌어올려진 듯이 동작함

위의 예를 다시 가져와 Record, outer와 호이스팅의 관계를 살펴보자

당연히 호이스팅이 가능한 이유는 진짜 물리적으로 코드를 끌어오기 때문이 아니다. 자바스크립트 엔진이 먼저 전체 코드를 스캔하며 변수 정보를 실행 컨텍스트(Record)에 저장하기 때문!

console.log(x); // undefined
var x = 'xxx'; // xxx로 업데이트해서 기록

function foo () { 
  var y = 'yyy'; //  yyy로 업데이트
  
  function bar () { 
    var z = 'zzz'; // zzz로 업데이트
    console.log(x + y + z);
  }
  bar();
}

foo();

1. 생성 단계(Creation Phase)

: Execution Context 생성, 선언문만 실행에 환경 레코드에 기록

변수

  • 전역 컨텍스트가 콜스택에 담기면 전체 코드를 스캔 → 선언할게 있다면 먼저 선언해 줌
  • 위 예에선 var로 선언했기 때문에 undefined로 초기화까지 해줌(선언 + 초기화)
  • const, let(선언만!) → ref 에러
    (const, let은 es6에 추가됨)

함수

  • 함수 표현식 사용
    : const ex = () => {} 변수 호이스팅과 동일하게 동작
  • 함수 선언문 이용
    : function 키워드 완성된 함수 객체를 생성해 환경 레코드에 기록
    따라서 선언 전에도 함수를 사용할 수 있음(지양하자)

2. 실행 단계(Execution Phase)

: 선언문 외 나머지 코드 순차적으로 실행, 환경 레코드를 참조하거나 업데이트 함


2-2. 외부환경 참조(feat, outer/렉시컬 환경)

식별자 결정

: 코드에서 변수나 함수의 값을 결정하는 것

outer

호출된 함수가 선언될 당시 LexicaEnvironment를 참조하는 포인터 → 바깥 렉시컬 환경으로 넘어갈 수 있는 사다리!

따라서 이전 실행 컨텍스트의 환경 레코드에 저장된 식별자도 참조할 수 있다

위의 예를 보면 이런식으로 동작한다는 것이다

console.log(x + y + z)
bar()  → 
z ㅇㅋ, x,y는? 
- outer 바깥 렉시컬 환경으로! → 
y ㅇㅋ, x는? 
- outer 바깥 렉시컬 환경으로! → 
x ㅇㅋ
만약 전역에서도 없으면 ref 에러!

요약

실행컨텍스트

:코드를 실행하는데 필요한 환경을 제공하는 객체

LexicalEnvironment

: 현재 실행 컨텍스트가 실행되기 위한 여러 정보를 담음

EnvironmentRecord(환경 레코드)

: 식별자에 대한 정보를 담음(feat, hosting)

OuterEnvironmentReference(outer/ 렉시컬 환경)

: 상위 렉시컬 환경을 차조해 스코프 체인을 가능케 함


참조
https://medium.com/crocusenergy/js-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-2b8ab8da4f4
https://www.youtube.com/watch?v=EWfujNzSUmw&t=17s

profile
개발자로 성장하기 위한 아카이브 😎

0개의 댓글