Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

23-3장 실행 컨텍스트 - 강철원 #975

Merged
merged 1 commit into from
Dec 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions docs/23_실행 컨텍스트/강철원B.md
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,117 @@ foo(); // 6
2. 외부 렉시컬 환경에 대한 참조 Outer Lexical Enviroment Reference

외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킵니다. 이때 상위 스코프란 외부 렉시컬 환경, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 말합니다. 외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드 리스트인 스코프 체인을 구현합니다.

## 6. 실행 컨텍스트의 생성과 식별자 검색 과정

```js
var x = 1;
const y = 2;

function foo(a){
var x = 3;
const y = 4;

function bar(b){
const z = 5;
console.log(a+b+x+y+z);
}
bar(10);
}

foo(20);
```

### 1) 전역 객체 생성

전역 객체는 전역 코드가 평가되기 이전에 생성된다.
이때 전역 객체에는 빌트인 전역 프로퍼티와 빌트인 전역 함수, 그리고 표준 빌트인 객체가
추가되며 동작 환경(클라이언트 사이드 또는 서버 사이드) 에 따라
클라이언트 사이드 Web API 또는 특정환경을 위한 호스트 객체를 포함한다.

전역 객체도 `Object.prototype`을 상속받는다.
즉, 전역 객체도 `프로토타입 체인의 일원`이다.

```js
// Object.prototype.toString
window.toString(); // "[object Window]"

window.__proto__.__proto__.__proto__.__proto__ === Object.prototype; // true

```

### 2) 전역 코드 평가

👍 전역 코드 평가 진행 순서

전역 실행 컨텍스트 생성

전역 렉시컬 환경 생성

2.1 전역 환경 레코드 생성

2.1.1 객체 환경 레코드 생성

2.1.2 선언적 환경 레코드 생성

2.2 this 바인딩

2.3 외부 렉시컬 환경에 대한 참조 결정

### 3) 전역 코드 실행

이제 전역 코드가 순차적으로 실행됩니다. 변수 할당문이 실행되어 전역 변수 x, y에 값이 할당되고foo 함수가 호출됩니다.

변수 할당문, 함수 호출문을 실행하려면 먼저 선언된 식별자인지 확인합니다. 또한 동일한 이름의 식별자가 다른 스코프에 존재한다면 어느 스코프의 식별자를 참조할지 결정하는데 이를 식별자 결정(identifier resolution)이라 합니다.

식별자 결정을 위해 식별자를 검색할 때는 실행 중인 실행 컨텍스트에서 식별자를 검색하기 시작합니다. 만약 해당 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색할 수 없으면 상위 스코프로 이동하여 식별자를 검색합니다.

⇒ 이것이 스코프 체인의 동작 원리
전역 렉시컬 환경은 스코프 체인의 종점이므로 전역 렉시컬 환경에서 검색할 수 없는 식별자는 참조 에러(ReferenceError)를 발생시킵니다.

### 4) foo 함수 코드 평가

foo 함수가 호출되면 전역 코드의 실행을 일시 중단하고 foo 함수 내부로 코드의 제어권이 이동합니다.

그리고 함수 코드를 다음 순서로 평가합니다.

1. 함수 실행 컨텍스트 생성
2. 함수 렉시컬 환경 생성
2.1 함수 환경 레코드 생성
2.2 this 바인딩
2.3 외부 렉시컬 환경에 대한 참조 결정

### 5) foo 함수 코드 실행

이제 런타임이 시작되어 `foo` 함수 코드가 순차적으로 실행됩니다. 매개변수에 인수가 할당되고, 변수 할당문이 실행되어 지역 변수 x,y에 값이 할당됩니다. 그리고 함수 `bar`가 호출됩니다.

이때 식별자 결정을 위해 실행 중인 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색하기 시작합니다. 현재 실행 중인 실행 컨텍스트는 foo 함수 실행 컨텍스트이므로 foo 함수 렉시컬 환경에서 식별자 `x`, `y`를 검색해서 검색된 식별자에 값을 바인딩됩니다. 만약 식별자가 없으면 상위 렉시컬 환경으로 이동하여 식별자를 검색합니다.

### 6) bar 함수 코드 평가

`bar` 함수가 호출되면 `bar` 함수 내부로 코드의 제어권이 이동하여 bar 함수 코드를 평가하기 시작합니다. 실행 컨텍스트와 렉시컬 환경의 생성 과정은 foo 함수 코드 평가와 동일합니다.

### 7) bar 함수 코드 실행

이제 런타임이 시작되어 bar 함수 코드가 순차적으로 실행됩니다. 매개변수에 인수가 할당되고, 변수 할당문이 실행되어 지역 변수 `z`에 값이 할당됩니다. 그리고 `console.log(a+b+x+y+z)`가 실행됩니다.

### 8) bar 함수 코드 실행 종료

`console.log` 메서드가 호출되고 종료하면 더는 실행할 코드가 없으므로 bar 함수 코드의 실행이 종료됩니다. 이때 실행 컨텍스트 스택에서 `bar` 함수 실행 컨텍스트가 `pop`되어 제거되고 스택에 남아있는 `foo` 함수 실행 컨텍스트가 실행중인 실행 컨텍스트가 됩니다.

`bar` 함수 실행 컨텍스트가 제거되었다고 해서 bar 함수 렉시컬 환경까지 즉시 소멸하는것은 아닙니다. 객체를 포함한 모든 값은 누군가에 의해 참조되지 않을때 비로소 가비지 컬렉터에 의해 메모리 공간의 확보가 해제되어 소멸합니다.

렉시컬 환경은 실행 컨텍스트에 의해 참조되기는 하지만 독립적인 객체입니다. 객체를 포함한 모든 값은 누군가에 의해 참조되지 않을 때 비소로 가비지 컬렉터에 의해 메모리 공간의 확보가 해제되어 소멸합니다.

`bar` 함수 실행 컨텍스트가 소멸되었다 하더라도 `bar` 함수 렉시컬을 누군가 참조하고 있다면 `bar` 함수 렉시컬 환경은 소멸하지 않습니다.

### 9) foo 함수 코드 실행 종료

`foo` 함수도 더 이상 실행할 코드가 남아있지 않으므로 foo 함수 코드의 실행이 종료됩니다. 실행 컨텍스트 스택에서 `foo` 함수 실행 컨텍스트가 `pop`되어 제거되고 전역 컨텍스트가 길생중인 실행 컨텍스트가 됩니다.

### 10) 전역 코드 실행 종료

`foo` 함수가 종료되면 더는 실행할 전역 코드가 없으므로 전역 코드의 실행이 종료되고 전역 실행 컨텍스트도 스택에서 `pop` 되어 실행 컨텍스트 스택에는 아무것도 남아있지 않게 됩니다.



Loading