2023. 5. 25. 20:28ㆍFront-end/Javascript
자바스크립트의 실행 컨텍스트란?
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
어떤 실행 컨텍스트가 활성화되는 시점에 다음과 같은 일을 한다.
1. 호이스팅( 선언된 변수를 위로 끌어올린다)
2.외부 환경정보 구성
3. this값 바인딩
실행 컨텍스트들은 콜스택이란 자료구조에 쌓이는데 이걸 이해하기 위해 스택이 뭔지 알아야한다.

스택(stack)은 밑에서 부터 쌓이는 구조로 LIFO(Last In First Out)의 구조를 가진다.(마지막에 들어온게 먼저 나간다)
반대로 큐(Queue)는 FIFO(First In First Out)구조로 되어있다.
콜스택도 위의 스택과 같은 구조로 되어있다.
실행할 코드에 제공할 환경 정보들을 모아놓은 객체인 실행 컨덱스트를 콜스택에 쌓아올린다.
가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장한다.
컨텍스트의 구성방법은 여러가지가 있지만 흔히 구성하는 함수에 대해 알아보자
// ---- 1번
var a = 1;
function outer() {
function inner() {
console.log(a); //undefined
var a = 3;
}
inner(); // ---- 2번
console.log(a);
}
outer(); // ---- 3번
console.log(a);
위와 같은 코드를 실햏할 때 컨텍스트의 구성 순서는
코드실행 => 전역(in)=> 전역(중단) => outer(in)=> outer(중단) => inner(in) => inner(out) => outer(재개)=> outer(out) =>전역(재개)=> 전역(out) => 코드종료
위와 같이 진행된다.함수가 선언되는 게 아닌 호출되는 시점을 기준으로 한다.
결국 특정 실행 컨텍스트가 생성되는(또는 활성화 되는) 시점이 콜스택의 맨 위에 쌓이는 순간이고,
곧 현재 실행할 코드에 해당 실행 컨텍스트가 관여하게 되는 시점을 의미한다.
실행 컨텍스트 객체의 실체 (담기는 정보)
1. VariableEnvironmentb
a. 현재 컨텍스트 내의 식별자 정보(=record)를 갖고있다.( ex) var a = 3 인 경우 var a)
b. 외부 환경 정보(=outer)를 갖고 있다.
c. 선언 시점 LexicalEnvironment의 snapshot이다.
2. LexicalEnvironment
a. 위의VariableEnvironment와 동일하지만 변경사항을 실시간으로 반영한다.
3.ThisBinding
a. this 식별자가 바라봐야할 객체를 지정한다.
VariableEnvironment, LexicalEnvironment ?
실행 컨텍스트에 있는 이 두가지의 항목은 완벽하게 동일하다. 그러나 스냅샷 유지여부가 다르다.
VE는 스냅샷을 유지하고 LE는 스냅샷을 유지하지 않고 실시간으로 변경사항을 반영한다.
(실행 컨텍스트를 생성할 때, VE에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LE를 만들고 이후엔 LE를 주로 활용한다.)
둘 다 구성 요소가 동일하다고 했는데
environmentRecord(=record)와 outerEnvironmentReference(=outer)로 구성된다.
environmnetRecord 의 역할, 호이스팅
현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장(수집)된다.
수집 대사은 함수에 지정된 매개변수 식별자, 함수 자체, var로 선언된 변수 식별자 등이다
컨텍스트 내부를 처음부터 끝까지 순서대로 훑어가며 수집( 코드가 실행되는 건 X)
여기서 호이스팅이란 개념이 나오는데 이는 변수를 수집하는 과정과 결과에서 나온 가상개념이다.
호이스팅이란?
변수의 정의가 그 범위에 따라 선언과 할당으로 분리되어 변수의 선언을 항상 컨텍스트 내의 최상위로 끌어올리는 것을 의미
호이스팅의 규칙
1. 매개변수 및 변수는 선언부를 호이스팅 한다.
function a (x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
위와 같은 코드가 있을 때 매개변수로 들어온 변수를 JS 엔진은똥같이 이해한다.
그러므로 다시 쓰면
function a () {
var x = 1;
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
이제 호이스팅이 적용되면 어떤 순서일까?
function a () {
var x;
var x;
var x;
x = 1;
console.log(x);
console.log(x);
x = 2;
console.log(x);
}
a(1);
변수의 선언부분이 모두 끌어올려진 이런 모습이다.
그래서 일반적인 코드의 순서로 예상하게 되면 예측을 할 수 없다.
호이스팅 규칙 2. 함수 선언은 전체를 호이스팅 한다.
function a () {
console.log(b);
var b = 'bbb';
console.log(b);
function b() { }
console.log(b);
}
a();
다시 이런 코드가 있다면 호이스팅이 적용되면 어떻게 될까?
function a () {
var b; // 변수 선언부 호이스팅
function b() { } // 함수 선언은 전체를 호이스팅
console.log(b);
b = 'bbb'; // 변수의 할당부는 원래 자리에
console.log(b);
console.log(b);
}
a();
위처럼 함수는 전체를 호이스팅 해온다.
여기서 함수의 표현 2가지 방식(함수 선언문, 표현식)을 생각해보면
function a ( ) { /* ... */ } / 함수 선언문
var b = function () / 함수 표현식
두 함수의 호이스팅 방식의 차이가 있을까?
함수 선언문의 경우 할당이 없고 정의부만 존재하기 때문에 호이스팅 되면 함수 전체가 호이스팅 되지만
정의한 function을 별도 변수에 할당하는 함수 표현식의 경우 함수가 아닌 선언부만 호이스팅 된다.
var multiply;
console.log(sum(1, 2));
console.log(multiply(3, 4));
multiply = function (a, b) { // 변수의 할당부는 원래 자리
return a + b;
};
위처럼 함수 표현식으로 사용했을 경우 함수의 선언부만 호이스팅된다.
코드가 길어질 경우 함수 선언문으로 사용할 경우 예상치 못한 에러가 발생할 수 있다.
함수 표현식을 사용하는 습관을 들이자
LexicalEnvironment - 스코프(scope), 스코프 체인(scope chain)
스코프는 식별자에 대한 유효범위를 의미한다.
스코프 체인은 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것이다.

지금까지 LexicalEnvironment 의 구성요소 record와 outer중 record를 알아봤고
이제 outerEnvironmentReference(=outer)에 대해 알아보자
outer의 역할을 한마디로 정의하면 스코프 체인이 가능토록 하는 것(외부 환경의 참조 정보)
outer는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.
예를 들어 A함수 내부의 B함수 선언 => B함수 내부에 C함수 선언 한 경우엔 ?
타고 타고 올라가다 전역 컨텍스트의 LexicalEnvironment를 참조하게 된다.
outer는 오직 자신이 선언된 시점의 LE를 참조하고 가장 가까운 요소부터 차례로 접근 가능하다.
각각의 실행 컨텍스트는 LE안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어 있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다.
'Front-end > Javascript' 카테고리의 다른 글
| Javascript datatype/Memory, data (0) | 2023.05.24 |
|---|