diff --git "a/clicelee/04\352\260\225/04\352\260\225.md" "b/clicelee/04\352\260\225/04\352\260\225.md" index 9ed3282..2cb55cb 100644 --- "a/clicelee/04\352\260\225/04\352\260\225.md" +++ "b/clicelee/04\352\260\225/04\352\260\225.md" @@ -29,7 +29,9 @@ 10+20을 연산할때, 우선 10과 20을 메모리 셀에 저장(write)한다 그리고 연산을 할때 메모리 셀을 읽어 10과 20이라는 숫자를 얻어 낸다 -![[IMG_50D55E86D0E7-1.jpeg]] + +![](https://i.imgur.com/SbRtHig.png) + ### 값을 식별하기 위한 역할 @@ -48,7 +50,9 @@ ### 정리 -![[IMG_1BFE577289BD-1.jpeg]] + +![](https://i.imgur.com/IoTHxaB.png) + 용어를 다시 정리하자면 변수에 값을 저장하는 것을 할당, 대입, 저장(assignment) 이라고 하고 @@ -62,7 +66,9 @@ 대신 `메모리 주소`를 구별한다 식별자가 기억하고 있는 메모리 주소를 읽고, 그 다음 메모리에 담긴 값을 읽는 과정이 이루어지는 것이다 -![[IMG_EFED7B257E7B-1.jpeg]] + +![](https://i.imgur.com/oBjPPwH.png) + >[!note] 식별자 >식별자는 메모리 주소에 붙인 이름이다 @@ -88,7 +94,9 @@ ES6 전에는 `var` 키워드 밖에 없었지만, 이후 `let`과 `const`가 2. 초기값이 설정된다 `var score=0;` 처럼 사용자가 초기화 해주지 않은 경우에는 값이 `undefined`로 자동 초기화 된다 -![[IMG_F39B3F942C5F-1.jpeg]] + +![](https://i.imgur.com/pZGiIWf.png) + undefined는 자바스크립트에서 제공하는 원시 타입의 값이다 자세한 내용은 6장의 [[데이터 타입]] 에서 자세히 알아볼 수 있다 @@ -119,7 +127,9 @@ undefined는 자바스크립트에서 제공하는 원시 타입의 값이다 Javascript는 **인터프리터 언어**임과 동시에 **컴파일 언어**다. 그래서 이러한 특징이 존재한다. ## 호이스팅(Hoisting)의 개념 -![[Screenshot 2024-07-15 at 11.52.16 AM.png]] + +![](https://i.imgur.com/fQste2q.png) + 호이스팅(Hoisting)은 JavaScript에서 변수와 함수 선언이 스코프의 상단으로 끌어올려지는 특징이다 코드 실행 전에 **JavaScript 엔진**에 의해 처리된다 @@ -252,7 +262,9 @@ var score=80; > 변수 선언과 값의 할당은 2개의 문으로 나누어져 각각 실행되며 > 실행 시점도 서로 다르다. 변수 선언이 먼저 이루어진다(이때 초기 할당값은 undefined) -![[IMG_F57981D08232-1.jpeg]] + +![](https://i.imgur.com/LAvuNxY.png) + # 4.6 값의 재할당 @@ -269,7 +281,9 @@ undefined, 80 처럼 사용되지 않는 값은 ==가비지 콜렉터에 의해 단! 메모리에서 언제 해제되는지는 모른다 js개발자가 *메모리 주소를 이용해 값에 접근하면 안 된다*는 것을 다시 한번 기억하고 넘어가자 -![[IMG_36D21E32DCD1-1.jpeg]] + +![](https://i.imgur.com/yI21KBQ.png) + >[!note] unmanaged lang VS managed lang > ##### unmanaged language @@ -303,17 +317,21 @@ js개발자가 *메모리 주소를 이용해 값에 접근하면 안 된다*는 3. 예약어는 식별자로 사용할 수 없다 ## 예약어 -![[Pasted image 20240715223005.png]] + +![](https://i.imgur.com/zfS2eUI.png) + ## 영어 이외의 다른 언어로 이루어진 식별자: 한글 식별자 ES5부터 식별자를 만들 때 유니코드 문자를 허용하기 때문에 한글, 일본어 식별자도 사용할 수 있다 책에서는 한글 식별자를 비추천 했다 -그러나 토스에서는 한글로 짓는 변수를 짓는 *세종대왕 프로젝트*를 진행한 적이 있다 +한편 토스에서는 한글로 짓는 변수를 짓는 *세종대왕 프로젝트*를 진행한 적이 있다 관련 게시물: [세종대왕 프로젝트](https://tosspayments-dev.oopy.io/chapters/frontend/posts/hangul-coding-convention) -![[Screenshot 2024-07-15 at 10.33.28 PM.png]] + +![](https://i.imgur.com/U7ihYiW.png) + (아직까지 사용하는지는 모르겠다) diff --git "a/clicelee/23\354\236\245 \354\213\244\355\226\211 \354\273\250\355\205\215\354\212\244\355\212\270.md" "b/clicelee/23\354\236\245 \354\213\244\355\226\211 \354\273\250\355\205\215\354\212\244\355\212\270.md" new file mode 100644 index 0000000..4b7524a --- /dev/null +++ "b/clicelee/23\354\236\245 \354\213\244\355\226\211 \354\273\250\355\205\215\354\212\244\355\212\270.md" @@ -0,0 +1,390 @@ + + +# 들어가기 앞서... +실행 컨텍스트는 자바스크립트의 동작원리를 담고 있는 핵심 개념이다 +실행 컨텍스트를 바르게 이해해야, 스코트를 기반으로 바이딩을 관리하는 방법과, 호이스팅이 발생하는 이유, 클로저의 동작 방식, 이벤트 핸들러와 비동기 처리 방식을 이해할 수 있다 + + +# 23.1 소스코드의 타입 +ECMAScript에서는 소스코드를 4가지 타입으로 구분한다 +*4가지 타입의 소스코드는 실행 컨텍스트를 생성한다* + +| 전역코드 | 전역에 존재하는 소스코드를 말한다. 전역에 정의된 함수, 클래스 등의 내부 코드는 포함하지 않는다 | +| ------ | ------------------------------------------------------------ | +| 함수 코드 | 함수 내부에 존재하는 소스코드를 말한다. 함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않는다 | +| eval코드 | 빌트인 전역함수인 eval 함수에 인수로 전달되는 소스코드 그 자체를 말한다 | +| 모듈 코드 | 모듈 내부에 존재하는 소스코드를 말한다. 모듈 내부의 함수, 클래스 등의 내부 코드는 포함되지 않는다 | +이 4가지는, 실행 컨텍스트를 생성하는 과정과 관리 내용의 종류에 따라 4가지로 분류된것이다 + + +![](https://i.imgur.com/69fXczk.png) + +1. **전역 코드 (Global Code)**: + - 전역 코드란 전역 범위에서 실행되는 코드를 의미한다 + - 이 코드는 전역 실행 컨텍스트에서 평가됩니다. + - 전역 실행 컨텍스트는 JavaScript 실행의 가장 상위 레벨의 컨텍스트로, 전역 객체와 관련된 변수를 관리한다 + +2. **함수 코드 (Function Code)**: + - 함수 코드란 함수 내부에서 실행되는 코드를 의미한다 + - 이 코드는 함수 실행 컨텍스트에서 평가된다 + - 함수 실행 컨텍스트는 해당 함수의 변수, 매개변수, 그리고 이 함수 내에서 사용되는 this 값을 관리한다 + +3. **eval 코드 (eval Code)**: + - eval 코드는 JavaScript의 `eval()` 함수를 통해 실행되는 코드를 의미한다 + - 이 코드는 eval 실행 컨텍스트에서 평가된다 + - eval코드는 strict 모드에서 자신만의 ==독자적인 스코프를 생성==한다 + - eval 실행 컨텍스트는 eval 함수 내부에서만 사용되며, 함수가 호출된 컨텍스트에서의 변수를 직접 수정할 수 있다 + +4. **모듈 코드 (Module Code)**: + - 모듈 코드는 ES6에서 도입된 모듈 시스템을 통해 작성된 코드를 의미한다 + - 이 코드는 모듈 실행 컨텍스트에서 평가된다 + - 모듈 실행 컨텍스트는 각 모듈이 독립적으로 관리되며, 각 모듈은 자신의 범위와 변수를 가진다 + + +## 23.2 소스코드의 평가와 실행 +앞서 4가지 종류의 코드를 보았는데, 코드가 *평가* 되고 *실행*되었다 + +그럼 평가와 실행 된다는게 정확히 무엇을 말하는 걸까? +한문장으로 정리하고 넘어가자면, 평가는 코드를 실행하기 전에 어떤 변수와 어떤 함수가 있는지 미리 알아두는 단계이고, 실행은 평가가 끝난 뒤에 실제로 코드가 한줄 한줄 동작하는 과정을 의미한다 + +### 평가 + +![](https://i.imgur.com/nR3cIda.png) +소스코드 평과 과정에서는 실행 컨텍스트를 생성하고 선언문만 먼저 실행하여 생성된 변수를 스코프에 등록한다. + +예시를 통해 이해하자 +```js +var x; +x=1; +``` + +![](https://i.imgur.com/IibYYWq.png) + + + 위 예제를 2개의 과정으로 나누어 처리한다. + - 소스코드 평가 과정 + - 소스코드 평가 과정에서 변수 선언문 `var x;`를 먼저 실행한다. + - 변수 식별자 `x`는 실행 컨텍스트가 관리하는 스코프에 등록되고 `undifined`로 초기화된다. + - 소스코드 실행 과정 + - 변수 할당문 `x = 1;`이 실행된다. + - 이 때 `x` 변수에 값을 할당하려면 먼저 `x` 변수가 선언된 변수인지 확인해야 한다. + - 이를 위해 실행컨텍스트가 관리하는 스코프에 `x` 변수가 등록되어 있는지 확인한다. + - `x` 변수가 선언된 변수라면 값을 할당하고 할당 결과를 실행 컨텍스트에 등록하여 관리한다. + + + + + +이제 23.2가 끝나고, 23.3-실행 컨텍스트 부터 본 장의 주제에 대해 깊게 배운다. +하지만 내용이 진짜 너무 어렵다. +그래서 우선 제가 나름대로 정리한 내용을 읽고, 그 다음 모던 자바스크립트 딥 다이브로 넘어가도록 하겠습니다 + +✂️----------------------------------------------------------------------------------------✂️ +## 자바스크립트 실행 컨텍스트란? + +자바스크립트에서 실행 컨텍스트(Execution Context)는 코드가 실행될 때 필요한 모든 정보를 담고 있는 "상자"라고 생각할 수 있다. 이 상자는 자바스크립트가 코드를 어떻게 실행할지, 어떤 변수를 사용할지, 그리고 `this`가 무엇을 가리키는지 등을 결정하는 중요한 역할을 한다. + +### 콜 스택(Call Stack)과 실행 컨텍스트 + +![](https://blog.kakaocdn.net/dn/xSsjO/btsJiHWZOlX/HGuVgKp7FJDrEJnVe4HQa1/img.png) + +출처: 자바스크립트 딥다이브 23장 + +자바스크립트는 함수를 호출할 때마다 새로운 실행 컨텍스트를 만들고, 이 실행 컨텍스트들은 **콜 스택(Call Stack)** 이라는 곳에 쌓이게 된다. 콜 스택은 실행 컨텍스트들이 차곡차곡 쌓이는 자료구조 "스택"처럼 쌓인다 + +- **콜 스택의 역할**: 자바스크립트는 콜 스택의 맨 위에 있는 실행 컨텍스트부터 차례로 코드를 실행한다. 함수가 호출되면 새로운 실행 컨텍스트가 만들어져 콜 스택에 추가되고, 함수가 끝나면 해당 컨텍스트는 콜 스택에서 제거된다. + +### 실행 컨텍스트가 어떻게 작동하는지 살펴보기 + +예제를 통해 실행 컨텍스트가 어떻게 작동하는지 살펴보자 +```js +var a = 1; + +function outer() { + function inner() { + console.log(a); + var a = 3; + } + inner(); + console.log(a); +} + +outer(); +console.log(a); +``` + +이 코드가 실행될 때, 다음과 같은 순서로 **실행 컨텍스트**와 **콜 스택**이 작동한다: + +1. **전역 컨텍스트 생성**: 코드가 실행되면서 가장 먼저 **전역 컨텍스트**가 만들어진다. 여기에는 전역에서 선언된 변수와 함수들이 포함된다. + - **콜 스택**: `[전역 컨텍스트]` + - **전역 컨텍스트의 정보**: + - 변수 `a = undefined` + - 함수 `outer` 정의 +2. **`var a = 1` 실행**: 전역 컨텍스트에서 `a` 변수에 `1`을 할당한다. + - **콜 스택**: `[전역 컨텍스트]` + - **전역 컨텍스트의 정보**: + - 변수 `a = 1` +3. **`outer()` 함수 호출**: `outer` 함수가 호출되면 **새로운 실행 컨텍스트**가 생성되고 콜 스택에 추가된다. + - **콜 스택**: `[전역 컨텍스트, outer 실행 컨텍스트]` + - **outer 컨텍스트의 정보**: + - 변수 `a = undefined` + - 함수 `inner` 정의 +4. **`inner()` 함수 호출**: `outer` 함수 안에서 `inner` 함수가 호출되면, **또 다른 실행 컨텍스트**가 생성되고 콜 스택에 추가된다. + - **콜 스택**: `[전역 컨텍스트, outer 실행 컨텍스트, inner 실행 컨텍스트]` + - **inner 컨텍스트의 정보**: + - 변수 `a = undefined` +5. **`console.log(a)` 실행 (inner 함수 안에서)**: `inner` 함수 안에서 `a`를 출력하려고 할 때, `inner` 컨텍스트 내에 `a`가 아직 할당되지 않았으므로 `undefined`가 출력된다. + - **출력**: `undefined` +6. **`var a = 3` 실행 (inner 함수 안에서)**: `inner` 함수 내부에서 `a`에 `3`을 할당한다. + - **콜 스택**: `[전역 컨텍스트, outer 실행 컨텍스트, inner 실행 컨텍스트]` + - **inner 컨텍스트의 정보**: + - 변수 `a = 3` +7. **`inner` 함수 종료**: `inner` 함수가 끝나면 `inner` 실행 컨텍스트는 콜 스택에서 제거된다. + - **콜 스택**: `[전역 컨텍스트, outer 실행 컨텍스트]` +8. **`console.log(a)` 실행 (outer 함수 안에서)**: 이제 `outer` 함수 안에서 `a`를 출력한다. 이때 `outer` 컨텍스트에 있는 `a`는 여전히 `undefined` 상태다. 왜냐하면 `outer` 함수 안에서는 `a`에 값을 할당한 적이 없기 때문이다. 그래서 전역 컨텍스트에 있는 `a` 값을 사용한다. + - **출력**: `1` +9. **`outer` 함수 종료**: `outer` 함수가 끝나면 `outer` 실행 컨텍스트도 콜 스택에서 제거된다. + - **콜 스택**: `[전역 컨텍스트]` +10. **마지막 `console.log(a)` 실행**: 이제 전역 컨텍스트로 돌아와서 `a`를 출력한다. 전역 컨텍스트에서 `a`는 `1`로 설정되어 있었으므로, `1`이 출력된다. + - **출력**: `1` + +## 요약하자면 + +- **실행 컨텍스트**는 자바스크립트가 코드를 실행하기 위해 필요한 **모든 정보**를 담고 있는 상자다. +- **콜 스택**은 **실행 컨텍스트들이 쌓이는** 장소다. 자바스크립트는 콜 스택의 맨 위에 있는 실행 컨텍스트부터 처리한다. +- 함수가 호출될 때마다 새로운 실행 컨텍스트가 만들어지고, 함수가 끝나면 그 실행 컨텍스트는 콜 스택에서 제거된다. + + +✂️----------------------------------------------------------------------------------------✂️ + +이해가 잘 되셨나요? +그럼 다시 *Modern Javscript Deep Dive 23.3 execution context* 에 대해 배워봅시다 + +## 23.3 실행 컨텍스트의 역할 +### 전역 코드 평가 +코드를 실행하려면 스코프, 식별자, 코드 실행 순서 등 여러 과정을 거친다 +이 모든 것을 관리하는 것이 *실행 컨텍스트*이다 +실행 컨텍스트는 소스코드를 실행하는데 필요한 환경을 제공하고 실제 코드의 결과를 관리한다 + `var` 키워드로 선언된 전역 변수와 함수 선언문으로 정의된 전역 함수는 전역 객체의 프로퍼티와 메서드가 된다. +## 3 전역 코드 실행 +전역 코드 평가 과정이 끝나면 런티암이 시작되어 전역 코드가 순차적으로 실행된다. +전역 변수에 값이 할당되고 함수가 호출된다. +함수가 호출되면 전역 코드의 실행을 일시 중단하고 코드 실행 순서를 변경하여 함수 내부로 진입한다. + + +### 3. 함수 코드 평가 + +```jsx +const x = 1; +const y = 2; + +function foo(a) { + canst x = 10; + canst y = 20; + + console.log(a + x + y); +} + +foo(100); + +console.log(x + y); +``` + +- 함수 코드 평가 과정을 거친다. +- 매개변수와 지역 변수 선언문이 먼저 실행된다. + - 생성된 매개변수와 지역 변수가 실행 컨텍스트가 관리하는 지역 스코프에 등록된다. +- 지역 변수처럼 사용할 수 있는 `arguments` 객체가 생성되어 지역 스코프에 등록된다. +- `this` 바인딩도 결정된다. + +### 4. 함수 코드 실행 + +- 함수 코드 평가 과정이 끝나면 런타임이 시작되어 함수 코드가 순차적으로 실행되기 시작한다. +- 매개변수와 지역 변수에 값이 할당되고 `console.log` 메서드가 호출된다. + - 먼저 식별자인 `console`을 스코프 체인을 통해 검색한다. + - 이를 위해 함수 코드의 지역 스코프는 상위 스코프인 전역 스코프와 연결되어야 한다. + - `console` 식별자는 스코프 체인에 등록되어 있지 않고 전역 객체에 프로퍼티로 존재한다. +- `log` 프로퍼티를 `console` 객체의 프로토타입 체인을 통해 검색한다. +- `console.log` 메서드에 인수로 전달된 표현식 `a + x + y`가 평가된다. +- `a + x + y`식별자는 스코프 체인을 통해 검색한다. + +- 코드가 실행되려면 스코프를 구분하여 식별자와 바인딩된 값이 관리되어야 한다. +- 중첩 관계에 의해 스코프 체인을 형성하여 식별자를 검색할 수 있어야 한다. +- 전역 객체의 프로퍼티도 전역 변수처럼 검색할 수 있어야한다. +- 함수 호출이 종료되면 함수 호출 이전으로 되돌아가기 위해 현재 실행 중인 코드와 이전에 실행하던 코드를 구분하여 관리해야 한다. +- 이처럼 코드가 실행되러면 스코프, 식별자, 코드 실행 순서 등의 관리가 필요하다. + +### 이 모든 것을 관리하는 것이 바로 실행 컨텍스트다. + +- 소스코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역이다. + - 식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리 + - 스코프와 코드 실행 순서 관리 +- 위 내용을 구현한 내부 매커니즘이다. +- 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다. +- 식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리한다. +- 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다. + +### 실행 컨텍스트 vs 콜스택 + +> "실행 컨텍스트 스택"과 "콜 스택"은 사실상 동일한 개념을 참조합니다. 두 용어 모두 현재 실행 중인 함수의 컨텍스트를 추적하는 스택 구조를 나타냅니다. +> +> 자바스크립트는 함수를 호출할 때마다 해당 함수의 실행 컨텍스트를 생성하고 스택에 푸시합니다. 이 스택이 바로 "실행 컨텍스트 스택" 또는 "콜 스택"입니다. 각 실행 컨텍스트는 함수의 실행 상태, 변수, 객체, 함수 선언 등에 대한 정보를 포함합니다. +> +> 함수의 실행이 완료되면 해당 함수의 실행 컨텍스트는 스택에서 팝되어 제거됩니다. 이렇게 해서 현재 실행 중인 함수가 어떤 것인지, 그 함수가 어떤 함수에 의해 호출되었는지 등을 추적할 수 있습니다. 이와 같은 과정을 통해 자바스크립트 엔진은 코드의 실행 순서를 정확히 관리할 수 있습니다. +> +> 따라서, "실행 컨텍스트 스택"과 "콜 스택"은 같은 개념을 가리키며, 둘 사이에는 별다른 차이가 없습니다. 일반적으로 이 둘은 서로 바꿔서 사용될 수 있으며, 주로 자바스크립트의 실행 컨텍스트와 관련된 주제를 논의할 때 사용됩니다. + + +## 23.4 실행 컨텍스트 스택 + +![](https://i.imgur.com/YPECZNX.png) + +코드를 읽으며 생성되는 실행 컨텍스트는 *스택* 자료구조 형태로 저장된다. +이를 ==실행 컨텍스트 스택== 이라고 부른다 +시간의 흐름에 따라 사용되는 컨텍스트가 넣어졌다가 + + +```jsx +const x = 1 + +function foo() { + const y = 2 + + function bar() { + const z = 3 + console.log(x + y + z) + } + + bar() +} + +foo() +``` + + + +1. 전역 코드의 평가와 실행 +2. foo 함수 코드의 평가와 실행 +3. bar 함수 코드의 평가와 실행 +4. foo 함수 코드로 복귀 +5. 전역 코드로 복귀 + +- 실행 컨텍스트 스택은 코드의 실행 순서를 관리한다. +- 스택의 최상위에 존재하는 실행 컨텍스트를 실행 중인 실행 실행 컨텍스트라 부른다. + +## 23.5 렉시컬 환경 + +식별자와 식별자에 바인딩된 값, 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트다. +실행 컨텍스트 스택이 코드의 실행 순서를 관리한다면 렉시컬 환경은 스코프와 식별자를 관리한다. +스코프를 구분하여 식별자를 등록하고 관리하는 저장소 역할을 하는 렉시컬 스코프의 실체다.실행 컨텍스트는 아래 두 컴포넌트로 구성된다. + - LexicalEnvironment + - VariableEnvironment +- 렉시컬 환경은 다음과 같이 두 개의 컴포넌트로 구성된다. + - Environment Record + - 스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩된 값을 관리하는 저장소다. + - Outer Lexical Environment Reference + - 상위 스코프를 가리킨다. + +## 23.6 실행 컨텍스트의 생성과 식별자 검색 과정 + +### 23.6.1 전역 객체 생성 +전역 객체는 전역 코드가 평가되기 이전에 생성된다. +- 전역 객체 + - 빌트인 전역 프로퍼티 + - 빌트인 전역 함수 + - 표준 빌트인 객체 + - Web API + - 호스트 객체 +전역 객체도 `Object.prototype`을 상속받는다. + - 전역 객체도 프로토타입 체인의 일원이다. + +### 23.6.2 전역 코드 평가 + +1. 전역 실행 컨텍스트 생성 +2. 전역 렉시컬 환경 생성 + 1. 전역 환경 레코드 생성 + 1. 객체 환경 레코드 생성 - BindingObject: `var` 키워드로 선언한 전역 변수와 `함수 선언문`, 전역 객체 + 2. 선언적 환경 레코드(개념적 블록) 생성 : `let`, `const` 키워드로 선언한 전역 변수 + 2. this 바인딩 - `[ [GlobalTh i sValue] ]` 내부 슬롯 + 3. 외부 렉시컬 환경에 대한 참조 결정: 현재 평가 중인 소스코드를 포함하는 외부 소스코드의 렉시컬 환경 + +### 23.6.3 전역 코드 실행 + +어느 스코프의 식별자를 참조하면 되는지 결정할 필요가 있다. 이를 식별자 결정이라 한다. +실행 중인 실행 컨텍스트에서 식별자를 검색하기 시작한다. + 검색할 수 없다면 외부 렉시컬 환경에 대한 참조가 가리키는 렉시컬 환경, 즉 상위 스코프로 이동하여 식별자를 검색한다. +전역 렉시컬 환경에서 검색할 수 없는 식별자는 참조 에러를 발생시킨다. + +### 23.6.4 foo 함수 코드 평가 + +```jsx +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. 함수 실행 컨텍스트 생성 +2. 함수 렉시컬 환경 생성 + 1. 함수 환경 레코드 생성: 매개변수, arguments 객체, 함수 내부에서 선언한 지역 변수와 중첩 함수 + 2. this 바인딩: foo 함수는 일반 함수로 호출되었으므로전역 객체를 가리킨다. + 3. 외부 렉시컬 환경에 대한 참조 결정: `평가`된 시점에 `실행 중`인 실행 컨텍스트의 렉시컬 환경 참조가 할당된다. + +### 23.6.5 foo 함수 코드 실행 + +식별자를 검색하기 시작한다. +실행 중인 실행 컨텍스트의 렉시컬 환경에서 식별자를 검색할 수 없으면 외부 렉시컬 환경에 대한 참조가 가리키는 렉시컬 환경으로 이동하여 식별자를 검색한다. + +### 렉시컬 환경의 소멸 + 실행 컨텍스트 스택에서 함수 실행 컨텍스트가 제거되었다고 해서 함수 렉시컬 환경까지 즉시 소멸하는 것은 아니다. +렉시컬 환경은 실행 컨텍스트에 의해 참조되기는 하지만 독립적인 객체다. +객체를 포함한 모든 값은 누군가에 의해 참조되지 않을 때 비로소 가비지 컬렉터에 의해 메모리 공간의 확보가 해제되어 소멸한다. + +## 23.7 실행 컨텍스트와 블록 레벨 스코프 + +`var` 키워드로 선언한 변수는 `오로지 함수의 코드 블록`만 지역 스코프로 인정하는 함수 레벨 스코프를 따른다. `let`, `const` 키워드로 선언한 변수는 `모든 코드 블록`을 지역 스코프로 인정하는 블록 레벨 스코프를 따른다. + +```jsx +let x = 1 + +if (true) { + let x = 10 + console.log(x) +} + +console.log(x) +``` + +`if` 문의 코드 블록을 위한 블록 레벨 스코프를 생성해야 한다. +이를 위해 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하여 기존의 전역 렉시컬 환경을 교체한다. + + +![](https://i.imgur.com/6EhdFs2.png) + + + +![](https://i.imgur.com/dXZk2Ty.png) + + + 이는 `if`문 뿐만 아니라 블록 레벨 스코프를 생성하는 모든 블록문에 적용된다. + +# 읽으면 좋은 글 + +[벨로그](https://velog.io/@kados22/FE-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94) +[쉽게 설명하는 글](https://yong-nyong.tistory.com/89) +[좋은 글](https://www.datoybi.com/execution-context/) +[짱짱 좋은 글! 제 글이에요^^](https://clice.tistory.com/entry/js-execution-context) +[예제로 설명해주는 글](https://chanhuiseok.github.io/posts/js-4/): 이 책에서는 인사이드 자바스크립트 라는 책을 추천한다 +[짧지만 핵심만 담은 글](https://catsbi.oopy.io/fffa6930-ca30-4f7e-88b6-28011fde5867) +실행컨텍스트 어느정도 이해를 한 것 같다면, 면접 질문 정리 글로 마무리 해보자! [클릭](https://velog.io/@kados22/FE-%EA%B8%B0%EC%88%A0-%EB%A9%B4%EC%A0%91-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80%EC%9A%94)