실행 컨텍스트(execution context)

Min·2021년 1월 14일
0

CoreJavaScript

목록 보기
2/4
post-thumbnail

1. 실행 컨텍스트란?

개념

실행할 코드에 제공할 환경 정보들을 모아놓은 객체

실행 컨텍스트 활성화때 생성되는 것

호이스팅, 외부 환경 정보를 구성, this 값을 설정, aruments

동일한 환경에 있는 코드들을 실행할 때

1) 필요한 환경 정보들을 모아 컨텍스트를 구성
2) 콜 스택에 쌓아 올린 후
3) 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행
동일한 환경 : 하나의 실행 컨텍스트를 구성할 수 있는 방법
ex) 전역공간, eval() 함수, 함수 등

컨텍스트를 구성하는 방법

함수를 실행하면 콜스택에 쌓이게 된다.
전역 컨텍스트 -> outer -> inner

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

실행 컨텍스트가 활성화될 때 자바스크립트 엔진은
해당 컨텍스트에 관련된 코드들을 실행하는 데
필요한 환경 정보들을 수집해서
실행 컨텍스트 객체에 저장한다.
(개발자가 객체 확인 불가능)

VariableEnvironment

environmentRecord(snapshot) + outerEnvironmentReference(snapshot)

현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보
선언 시점의 LexicalEnvironment의 스냅샷으로, 변경 사항은 반영되지 않는다.

LexicalEnvironment

environmentRecord + outerEnvironmentReference

처음에는 VariableEnvironment와 같지만 변경 사항이 실시간으로 반영된다.

ThisBinding

this 식별자가 바라봐야 할 대상 객체

2. VariableEnvironment

LexicalEnvironment와 동일하지만 최초 실행 시의 스냅샷을 유지

실행 컨텍스트 생성시

1) VariableEnvironment에 정보를 먼저 담는다.
2) 이를 그대로 복사해서 LexicalEnvironment를 만든다.
3) 이후에는 LexicalEnvironment를 주로 활용

3. LexicalEnvironment

사전적 환경

"현재 컨텍스트의 내부에는 a, b, c와 같은 식별자들이 있고 그 외부 정보는 D를 참조하도록 구성되어 있다."

1) environmentRecord와 호이스팅

함수 실행 순서

함수의 실행 컨텍스트가 생성 -> environmentRecord 식별자 정보 수집 -> 호이스팅 -> 스코프 체인 정보를 수집, this를 바인딩

정보수집

environmentRecord에는
현재 컨텍스트와 관련된 코드의 식별자 정보들
(매개변수의 이름, 함수 선언, 변수명 등)을
순서대로 수집하며 저장된다.
식별자에 어떤 값이 할당될 것인지는 관심이 없다.

참고 : 전역 실행 컨텍스트에는 전역 객체를 활용
(내장 객체가 아닌 호스트 객체)
1) 브라우저 : window
2) Node.js : global

호이스팅

environmentRecord 과정에서 호이스팅이 사용된다.

변수는 선언문만 끌어올리며,
변수의 할당부는 원래 자리에 남겨둔다.
함수선언은 전체를 끌어올린다.

변수 정보를 수집하는 과정을
더욱 이해하기 쉬운 방법으로 대체한 가상의 개념이다.
(자바스크립트 엔진이 실제로 하진 않는다.)

호이스팅이 끝난 상태에서는
함수 선언문은 함수명으로 선언한 변수에
함수를 할당한 것처럼 여길 수 있다.

var b;
function b () {}
var b;
var b = function b() {}

함수 선언문과 함수 표현식

변수명으로 함수를 호출한다.

// 1. 함수 선언문. 함수명 a가 곧 변수명.
function a () {}
a(); // OK!

// 2. (익명) 함수 표현식. 변수명 b가 곧 함수명.
var b = function() {}
b(); // OK!!


// ex) 호이스팅 전
function sum (a, b) { //함수 선언문은 전체를 호이스팅
	return a + b;
}
var multiply = function (a, b) { //변수는 선언부만 끌어올려진다.
	return a * b;
}

// ex) 호이스팅 후
var sum = function sum(a, b) { // 함수 선언문은 전체를 호이스팅
	return a + b;
}
var multiply; // 변수는 선언부만 끌어올려진다.

multiply = function (a, b) { // 변수의 할당부는 원래 잘리에 남겨둔다.
	return a * b;
}

// 3. 기명 함수 표현식. 변수명은 c, 함수명은 d.
var c = function d() {}
c(); // OK!!
d(); // ERROR!

기명 함수 표현식

외부에서는 함수명으로 함수를 호출할 수 없으며
오직 함수 내부에서만 접근 가능하다.

함수 내부에서 재귀함수를 호출하는 용도로
함수명 사용할 수 있다.

이제는 모든 브라우저들이 익명 함수 표현식의 변수명을
함수의 name 프로퍼티에 할당하고 있다.

상대적으로 함수 표현식이 함수 선언식보다 안전하다.

2) 스코프, 스코프 체인, outerEnvironmentReference

스코프

식별자에 대한 유효범위이다.

어떤 경계 A의 외부에서 선언한 변수는
외부뿐 아니라 A의 내부에서도 접근이 가능하지만,
A의 내부에서 선언한 변수는
오직 A의 내부에서만 접근할 수 있다.

ES5까지는 전역공간을 제외하면
오직 함수에 의해서만 스코프가 생성

ES6에서는 함수 스코프, 블록 스코프(let, const, class, stric mode에서의 함수 선언 등)로 나뉜다.

스코프 체인

outerEnvironmentReference는
현재 호출된 함수가
선언될 당시(과거 시점)LexicalEnvironment를 참조

ex) outer은 inner의 LexicalEnvironment를 참조

outerEnvironmentReference

연결리스트 형태로 오직 자신이 선언된 시점의 LexicalEnvironment만 참조하고 있으므로
가장 가까운 요소부터 차례대로만 접근할 수 있고
다른 순서로 접근하는 것은 불가능하다.

여러 스코프에서 동일한 식별자를 선언한 경우
무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능

ex) 전역 컨텍스트 -> outer -> inner

/* 1. 전역 컨텍스트 활성화
- environmentRecord : { a, outer }
- outerEnvironmentReference : 선언 시점이 없으므로 아무것도 담기지 않는다.
- this : 전역 객체 */
var a = 1;
/* 2. outer 컨텍스트 활성화
- environmentRecord : { inner }
- outerEnvironmentReference : outer 함수가 선언될 당시의 LexicalEnvironment가 담기며 전역 공간에서 선언되어 전역 컨텍스트의 LexicalEnvironment를 참조복사한다.
{ GLOBAL, { a, outer } === { 실행컨텍스트 이름, { environmentRecord }
- this : 전역 객체 */
var outer = function() {
  	/* 3. inner 컨텍스트 활성화
	- environmentRecord : { a }
	- outerEnvironmentReference : { outer, { inner } }
	- this : 전역 객체 */
	var inner = function () {
    	console.log(a); // undefined
        var a = 3;
    };
  	inner();
  	console.log(a); // 1(전역 LexicalEnvironment) environmentRecord를 계속 찾아 나간다.
};
outer();
console.log(a);

전역변수와 지역변수

전역변수 : 전역 공간에서 선언한 변수
ex: 전역 스코프에서 선언한 a와 outer

지역변수 : 함수 내부에서 선언한 변수
ex:
1) outer 함수 내부에서 선언한 inner
2) innter 함수 내부에서 선언한 a

전역변수의 사용을 최소화 하는 방법 :
즉시실행함수, 네임스페이스, 모듈 패턴, 샌드박스 패턴 등.
모듈관리 도구인 AMD나 CommonJS, ES의 모듈 등.

4. this

실행 컨텍스트의 thisBinding에는
this로 지정된 객체가 저장되는데
실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우 this에 전역 객체가 저장된다.

그 밖에는 함수를 호출하는 방법에 따라
this에 저장되는 대상이 달라진다.

profile
slowly but surely

0개의 댓글