Core js - 실행 컨텍스트

heyhey·2023년 10월 26일
0
post-thumbnail

실행 컨텍스트는 실행할 코드를 제공할 환경 정보들을 모아놓은 객체로, JS가 동적 언어로서의 성격을 잘 파악할 수 있는 개념입니다.

1. 실행 컨텍스트란

실행 컨텍스트는 동일한 환경에 있는 코드들을 실행할 때
필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 쌓아 올립니다.
가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장합니다.

실행 컨텍스트를 구성하는 방법은 함수를 실행하는 방법입니다.

실행컨텍스트가 실행되는 순서를 예시를 통해 알아보겠습니다.

// =========================(1)
var a = 1;
function outer(){
	function inner(){
			console.log(a)
			var a = 3;
	}
	inner(); // =========================(2)
	console.log(a);
}
outer(); // =========================(3)
console.log(a)

JS 코드를 실행시키면 전역 컨텍스트(1)가 콜 스택에 담기게 됩니다.
전역 컨텍스트라는 개념은 일반적인 실행 컨텍스트와 특별히 다를 것이 없습니다.

최상단의 공간을 코드 내부에서 별도의 실행 명령이 없어도 브라우저에서 자동 실행됩니다.

이렇게 코드를 진행하다가 (3)에서 outer() 함수를 호출하면, outer에 대한 환경 정보를 수집하여 Outer 실행 컨텍스트를 생성한 후 콜 스택에 담습니다.

콜스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 됐으므로 전역 컨텍스트와 관련된 코드의 실행을 중단하고, outer 함수 내부의 코드를 실행합니다.

다시 outer 안에서 inner (2) 함수의 실행 컨텍스트가 가장 위에 담기면 Outer 컨텍스트와 관련된 코드를 중단하고 Innner 함수 내부의 코드를 순서대로 진행합니다.

inner 함수가 실행되고 마지막 코드가 실행되며 inner 실행 컨텍스트가 콜스택에서 제거됩니다.

그러면 그 아래의 Outer 컨텍스트를 이어서 실행하고 마찬가지로 종료되면 전역컨텍스트가 실행됩니다.


실행 컨텍스트가 콜 스택 맨 위에 쌓이는 순간이 실행할 코드에 관여하게 되는 시점입니다. 이렇게 어떤 실행 컨텍스트가 활성화될 때 JS 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집하여 실행 컨텍스트 객체에 저장합니다.
이 객체에 담기는 정보들은 다음과 같습니다.

  • Variable Environment
    현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보
    선언 시점의 Lexical Environment 의 스냅샷
  • Lexical Environment
    처음에는 위와 동일하지만 변경 사항이 실시간으로 반영
  • This Binding
    this 식별자가 바라봐야 할 대상 객체

2. Variable Environment

Lexical Environment 과 담기는 내용은 같지만 최초 실행 시의 스냅샷을 유지한다 라는 점이 다릅니다.

처음 실행 컨텍스트를 생성시 Variable Environment에 정보를 담은 다음 이를 복사해서 Lexical Environment를 만들고, 이후에는 Lexical Environment를 주로 사용합니다.

3. Lexical Environment

Lexical Environment은 컨텍스트를 구성하는 환경 정보들을 모아 놓은 것이라고 할 수 있습니다.

3.1 environmentRecord & 호이스팅

environmentRecord 에는 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장됩니다.(함수에 지정된 매개변수 식별자, 함수 자체, 변수의 식별자... )
컨텍스트 내부를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집하게 됩니다.

참고
전역 실행 컨텍스트는 변수 객체를 생성하는 대신 JS 구동 환경이 별도로 제공하는 객체, 즉 전역 객체를 활용합니다. 전역 객체는 JS 내장 객체가 아닌 호스트 객체로 분류됩니다.

변수 정보를 수집게 되면, 식별자들을 최상단으로 끌어올린 다음 코드를 실행하게 됩니다. 이 개념이 호이스팅 개념입니다.

호이스팅의 규칙

function test(){
	var a ;
	a = 1
	console.log(a)// (1) ?
	var a ;
	console.log(a)// (2) ?
	var a ;
	a = 3;
	console.log(a) // (3) ?
}

1,2,3 에서는 어떤 값이 출력될까요?

예상으로는 1,undefined,3 이 출력되야 할 것 같은데 실제로는 1,1,3 이 나옵니다.
호이스팅을 시각적으로 보이게 적어보겠습니다.

function test(){
	var a ;
	var a ;
	var a ;
	a = 1
	console.log(a)// (1) ?
	console.log(a)// (2) ?
	a = 3;
	console.log(a) // (3) ?
}

변수 선언 부분을 위로 보내게 되면 확인하기가 쉽습니다.
함수도 마찬가지 입니다.

function test(){
	var a ;
	a = 1
	console.log(a)// (1) ?
	function a(){}
	console.log(a)// (2) ?
}

1은 1, 2는 function 이 나올 것 같지만 둘다 함수를 출력합니다.

함수에 대해서 더 알아보겠습니다.

함수 선언문과 함수 표현식

함수 선언문 : function 정의부만 존재하고 할당 명령이 없는 것
function a(){}

함수 표현식 : 별도의 변수에 할당하는 것
var a = function(){}

그래서 함수 선언문은 함수명이 정의되어 있어야 하는 반면, 함수 표현식은 없어도 됩니다.

이 두개의 실질적인 차이를 확인해보겠습니다.

실행 컨텍스트의 lexical Environment 는 두가지의 정보를 수집합니다. 여기서는 그 중에 envirenment Record 의 정보 수집 과정에서 발생하는 호이스팅을 확인합니다.

console.log(a) // (1)
console.log(b) // (2)
function a(){}
var b = function(){}

1번과 2번이 뭐가 나와야 할까요? 둘다 함수가 나올거같은데..
호이스팅을 통해 확인해보겠습니다.

function a(){};
var b;
console.log(a) // (1)
console.log(b) // (2)
b = function(){}

a 는 예상대로 진행됐지만 , 하지만 2는 b() 이렇게 실행시키려고 하면 not a function 에러가 납니다.

함수 선언문은 호이스팅 때문에 문제가 많이 일어납니다. 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어 씌우게 됩니다. 그래서 함수 표현식이 조금 더 안전하다고 볼 수 있습니다.

3-2 스코프 체인 , OuterEnvironmentReference

스코프란 식별자에 대한 유효범위입니다. ES5까지의 JS는 오직 함수에 의해서만 스코프가 생성되었습니다. 이렇게 안에서부터 바깥으로 차례로 검색해 나가는 것을 스코프 체인이라고 합니다. 그리고 이를 가능케 하는 것이 Lexical Environment 의 두번째 수집 자료인 OuterEnvironmentReference 입니다.

스코프 체인

OuterEnvironmentReference 는 현재 호출된 함수가 선언될 당시 Lexical Environment를 참조합니다. 현재 시점에서의 Lexical Enviroment에서 스코프를 올라가며 컨텍스트를 실행하게 됩니다.
여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하게 됩니다.

전역 공간에서는 전역 스코프에서 생성된 변수에만 접근할 수 있고, Outer 함수는 outer 및 전역 스코프에서 생성된 변수에 접근할 수 있습니다. inner 함수는 Outer와 전역 컨텍스트에 접근이 가능합니다.

여러군데에서 선언한 변수는 스코프 체인 상에 첫번째 인자, 즉 현재 scope의 lexicalEnvironment 부터 검색해서 올라갑니다. 외부 함수에서 내부 함수의 값에 접근을 못하는 것을 변수 은닉화라고 합니다.

this

실행 컨텍스트의 ThisBinding 에는 this 로 지정된 객체가 저장됩니다. 실행 컨텍스트 활성화 당시에 This가 지정되지 않을 경우 This에는 전역 객체가 저장됩니다. 그 밖에는 함수를 호출하는 방식에 따라 This에 저장되는 방식이 달라지게 됩낟.

profile
주경야독

0개의 댓글