실행컨텍스트

수박·2021년 8월 21일
0

JavaScript

목록 보기
22/22
post-thumbnail

실행컨텍스트


실행컨텍스트는 코드가 실행되기 위해 필요한 환경

이미지출처, 내용참고사이트

자바스크립트가 call Stack으로 코드를 처리하는 것은 알고있다.

이 Call Stack에 쌓이는 것은 함수다. 쌓인다고 해서 내부 로직이 실행되는 것이 아니다.

이 함수가 실행되려면 필요한 것들이 있다.

함수 내부에서 사용되는 변수나 전달받은 arguments, 내부 함수, 해당 함수의 스코프가 어떻게 되어있는지 등에 대한 관련 정보들이 어딘가에 선언되어있어야 작성된 함수가 올바르게 수행될 수 있다.

이 정보들을 담는 환경(공간)이 "실행컨텍스트"이다.

실행컨텍스트란, 코드가 실행되기 위해 필요한 환경이다.

실행컨텍스트 스택

Global EC는 브라우저 종료시까지 사라지지 않는다.

call stack과 같다보면 된다. Stack형태로 호출된 함수가 필요한 환경을 생성하고, 종료되면 소멸되기 때문이다.

실행컨텍스트(Execution Context) 스택은 call Stack처럼 함수단위로 쌓이고 종료되면 실행컨텍스트가 소멸된다.

실행컨텍스트 구성

추상적인 내용임으로 더 자세한 실행컨텍스트에 대한 구성은 블로그에서 읽어보면 도움이 됩니다.

실행컨텍스트는 함수 내에서 사용되는 변수, 인수, 파라미터 그리고 내부 함수들을 객체형태로 관리하는 Variable Object

해당 함수의 스코프 정보들을 갖는 Scope Chain

현재 컨텍스트를 가리키는 this객체로 구성되어있다.

하나하나 살펴봅시다 !

Variable Object

Argument, parameter의 차이 === 둘은 다르다.

VO에서는 변수, arguments, parameter, 내부함수선언에 대한 정보를 갖는다.

그러나 VO안에 저장되는 것은 아니다. 저장되는 공간은 AO(Activation Object)로 VO는 AO를 가리키는 참조자다.

함수컨텍스트의 경우 AO라하고, 전역 컨텍스트의 경우 argument가 빠진 GO를 가리킨다. 이외는 동일하다.

Scope Chain

스코프란, 특정 장소에 변수를 저장하고 후에 변수, 함수를 찾는데 필요한 규칙을 뜻합니다.

이전글에서 "스코프에게 a, b가 있는지 물어보고 없다면 스코프컬렉션에 추가, 있다면 그냥 지나친다"라고 했었다.

이 작업을 하는 시점이 컴파일 시점이고 그 중 렉싱단계에서 스코프가 결정된다.

많이 들었지만 잘 알지 못하는 바로 그 "렉시컬 스코프"가 맞다.

JS의 스코프는 렉스타임에 결정된다고 하여 "렉시컬 스코프"를 따른다고 불리우는 것이다.

함수의 선언문이 어디에 선언되었는지에 따라서 변수나 함수의 스코프가 결정되는 것이 렉시컬스코프라고 생각하면 된다.

Scope chain은 말 그대로 Scope들이 연결된 것으로 리스트의 형태를 갖는다.

Scope Chain의 Node가 가리키는 대상은 자신의 상위함수, 또는 전역 실행컨텍스트의 VO가 가리키는 대상이다.

넘 복잡해요

코드로 봅시다.

var x = 'xxx';

function foo () {
  var y = 'yyy';

  function bar () {
    var z = 'zzz';
    console.log(x + y + z);
  }
  bar();
}
foo();

foo함수 안에 bar함수가 정의되어있다.

bar의 AO에 없는 x, y를 참조하기 위해선 자신을 감싼 상위 함수로 넘어가서 확인한다.

이 때 사용되는게 바로 Scope Chain이다.

foo의 컨텍스트에 VO가 가리키는 AO안에 y에 대한 정보가 기록되어있다.

bar의 Scope Chain은 foo와 전역을 가리키는 리스트다.

현재 컨텍스트(bar)에 참조하려는 변수가 AO에 없다면, Scope chain이 가리키는 상위(foo, 전역) AO에서 찾아서 사용한다.

이를 "Scope Chaining"이라고 한다.

this

추가내용들은 따로 다룰 예정입니다.

현재 컨텍스트를 가리키는 객체라고 했는데, 해당 함수만을 고정으로 가리키는게 아니다.

함수의 호출방식에 따라 결정된다.

실행컨텍스트 생성순서

실행컨텍스트의 생성순서는 고정적이며 다음 순서를 따른다.

  1. Scope Chain 생성 및 초기화
  2. Variable 객체화
  3. this 결정

Scope Chain 생성 및 초기화

함수가 실행되면 SC의 첫 값을 AO로 설정한다.

리스트의 형태인 Scope Chain의 첫 Node는 VO가 가리킬 AO다.

그 후, foo를 호출한 컨텍스트의 AO의 foo property의 function object value에 지정된 [[scope]]값을 기반으로 현재 컨텍스트의 SC에 추가한다.

AO에 함수가 추가될 때 function Object가 값으로 들어가며, 그의 property에는 [[scope]]를 갖게된다.

[[scope]]란 해당 function Object가 실행되는 환경(사진에서는 GO)를 가리킨다.

이 함수가 실행되어 새로운 컨텍스트를 만들 때 [[scope]]를 기반으로 Scope Chain에 추가된다. (사진에서는 빨간색 1이 가리키는 GO 스코프노드가 추가된 것이다.)

Variable 객체화 실행

SC 단계가 종료되면 해당 단계가 실행된다.

이는 VO가 가리키는 AO또는 GO에 함수, 변수 등을 저장하는 단계다.

AO에 추가되는 순서는 다음과 같다.

  1. Parameter
  2. 함수선언문
  3. 변수선언문

2,3 단계에서 함수가 먼저 AO에 추가된다. 선언문이 먼저 처리되는 것.. 호이스팅 !

실행컨텍스트가 생성될 때, AO에 선언문들이 등록되는 것이 바로 호이스팅이다.

또한, 함수가 변수보다 먼저 등록되므로 함수 호이스팅 -> 변수 호이스팅의 순서를 갖게되는 것이다.

this 결정

선언처리 끝나고 this가 결정된다.

정리

JS는 컴파일 과정을 거친다.

코드가 실행될 때 컨텍스트 생성과정을 거친다.

전역코드에선 전역 컨텍스트를, 함수는 함수컨텍스트를 생성한다.

컴파일과정에서 선언된 선언문들의 스코프들을 결정짓는다.

이 때 결정된 스코프가 렉시컬 스코프다.

함수가 실행될 때 전역과 마찬가지로 실행컨텍스트가 생성되고 먼저 상위 코드의 [[scope]]를 기반으로 Scope Chain을 생성 및 초기화한다.

이후, VO객체화를 수행하는데 이때 사용할 함수, 변수 등의 정보를 AO에 등록한다.

마찬가지로 선언문부터 처리되므로 호이스팅이 발생한다. 함수 -> 변수 순서

마지막으로 해당 컨텍스트를 가리킬 this value가 결정되고 코드가 실행된다.

해당 컨텍스트에서 참조하는 변수가 AO에 없다면 Scope Chain을 따라 해당 값을 참조하기 위해 가리키는 상위 AO에 접근한다.

전역 컨텍스트까지 chain되며 없다면 null을 반환한다.

0개의 댓글