생각기록
2023-03-07 실행콘텍스트? 본문
🎈실행 컨텍스트란? (execution context)
실행할 코드에 제공할 환경 정보들을 모아놓은 객체
자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념
= 실행 컨텍스트는 자바스크립트 코드가 실행되는 환경이다.
모든 JavaScript 코드는 실행 컨텍스트 내부에서 실행된다고 생각하면 된다.
함수가 실행되면 함수 실행에 해당하는 실행 컨텍스트가 생성되고, js 엔진에 있는 콜 스택에 차곡차곡 쌓인다.
가장 위에 쌓여있는 컨텍스트와 관련 있는 코드를 실행하면서 (LIFO), 전체 코드의 환경과 순서를 보장하게 된다.
실행 컨텍스트는 식별자 ( 변수, 함수, 클래스 등의 이름) 를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 매커니즘으로, 실행 컨텍스트는 곧 JS 의 핵심 원리
실행 컨텍스트가 생성은 언제?
JS 엔진이 스크립트를 처음 마주할 때 전역 컨텍스트 생성하고, 콜 스택에 push 한다.
엔진이 스크립트를 쭉 읽어내려가고 함수 호출을 발견할 때마다 함수의 실행 컨텍스트를 스택에 push 한다.
함수 실행 컨텍스트는 함수가 실행될 때! 만들어진다는 점!!
선언이 아니라 실행시
실행 컨텍스트 종류
전역공간, 함수, eval()
- 전역 실행 컨텍스트: 전역 영역에 존재하는 코드.
모든 스크립트 코드는 전역 실행 컨텍스트 안에서 실행된다.
프로그램에 단 한 개만 존재하며 실행 컨텍스트의 기본이다. 함수 밖에 있는 코드는 전역 실행 컨텍스트에 있다.
브라우저의 경우에는 window객체, Node.js의 경우엔 global객체가 곧 전역 실행 컨텍스트가 된다.
- 함수 실행 컨텍스트: 함수 내에 존재하는 코드.
함수가 실행될 때마다 만들어지는 실행 컨텍스트이다.
각 함수는 고유의 실행 컨텍스트를 가지며, 함수가 실행되거나 call 될 때에만 생성된다.
- eval() 실행 컨텍스트: eval 함수로 실행되는 코드.
이제 쓰지 않는 eval() 함수에 의해 생성되는 실행 컨텍스트


js는 실행 컨텍스트가 활성화 되는 시점에서 다음과 같은 형상이 발생함
- 호이스팅이 발생한다 ( 선언된 변수를 위로 끌어올린다 )
- 외부 환경 정보를 구성한다
- this 값을 설정한다
이로 인해 다른 언어에서 발견할 수 없는 특이한 현상들이 발생한다.
실행 컨텍스트 구성
실행 컨텍스트는 다음과 같은 것들을 이용하면 call stack에 쌓이게 된다.
전역공간은 자동으로 컨텍스트로 구성된다.
함수를 실행한다
eval()함수를 실행한다
block 을 만든다 ES6+
일반적으로 함수를 이용한 실행 컨텍스트를 사용

실행 컨텍스트의 스택은 다음과 같은 순서로 실행
1. 프로그램 실행 [ 전역 컨텍스트 ]
2. Outer 실행 [ 전역 컨텍스트, outer ]
3. Inner 실행 [ 전역 컨텍스트, outer, inner ]
4. Inner 종료 [ 전역 컨텍스트, outer ]
5. Outer 종료 [ 전역 컨텍스트 ]
이러한 실행컨텍스트를 구성할 때 생기는 것들
실행 컨텍스트의 구조
- VariableEnvironment
- 현재 컨텍스트 내의 식별자(변수)들에 대한 정보
- 외부 환경 정보
- 선언 시점의 LexicalEnvironment의 스냅샷(변경사항 반영 X)
- LexicalEnvironment
- 처음에는 VariableEnvironment와 같음
- 변경 사항이 실시간으로 반영됨
- ThisBinding
- 식별자가 바라봐야 할 대상 객체
Variable Environment
VariableEnvironment에 담기는 내용은 LexicalEnvironment와 같지만, 최초 실행 시의 스냅샷을 유지한다. 실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음, 이를 복사해서 LexicalEnvironment를 만든다.
주로 활용하는 것은 LexicalEnvironment이다. 즉, VariableEnviroment는 스냅샷 유지를 목적으로 사용한다.
Lexcial Environment
LexicalEnvironment의 내부에는 environmentRecord와 outerEnvironmentReference로 구성돼 있다.
- environmentRecord로 인하여 호이스팅이 발생한다.
- outerEnvironmentReference로 인하여 스코프와 스코프체인이 형성된다.
참고 : https://www.youtube.com/watch?v=EWfujNzSUmw
Execution Context
- Record
- Outer
실행 컨텍스트 안에 Record, Outer 가 존재
1. Record 로 Js 호이스팅 이해
2. Outer 로 JS 스코프체이닝 이해
3. Execution Context 정리
JS 코드를 실행시키면, JS 엔진은 Call Stack 이라는 공간에
1. 전역 실행컨텍스트를 담는다.
2. 함수 실행 컨텍스트를 담는다.
가장 최근에 추가된 실행 컨텍스트만 활성
=> 즉 사진에서는 함수 A가 현재 활성화된 실행컨텍스트!

여기서 함수 A의 실행이 끝나면, 함수 A의 실행 컨텍스트가 사라짐
그럼 전역 실행컨텍스트로 돌아와 이 코드가 마지막라인까지 실행되면, 전역 실행컨텍스트도 사라짐
1. Record 로 Js 호이스팅 이해

Q. 아래 콘솔은 NetFlix가 잘 나올 것! 그럼 위에 콘솔은?
다른 언어에서는 오류가 날테지만! js에서는 오류가 발생하지 않고, undefined가 출력 됨
호이스팅 Hoisting
이렇게 선언 라인 전에도 에러가 나지 않고,변수를 참조할 수 있는 현상
선언문이 마치 최상단에 끌어올려진 듯한 현상, 호이스팅 현상 이라고 부름
Q. 이 현상이 발생하는 이유는?
선언문이 있는 코드라인을 물리적으로 최상단에 끌어 올렸기 때문 xx
js 엔진이 먼저 전체 코드를 스캔하면서 => 변수같은 정보를 실행컨텍스트 어딘가에 미리 기록해논다.
그런 공간을 환경 레코드 Environment Record 라고 합니다
환경 레코드 Environment Record
식별자와 식별자에 바인딩된 값을 기록하는 객체
Hoisting의 종류
- Variable Hoisting 변수 호이스팅
- Fuction Hoisting 함수 호이스팅
Variable Hoisting 변수 호이스팅
var
let, const

아까 사진의 코드를 실행한다면,
우선 전역 실행 컨텍스트 한 칸 생성해 콜스택에 넣습니다.

그 후 전체코드 스캔하면서 선언할게 있는지 찾아보고 있다면 먼저 선언해둠
선언하는 과정에 생성해둔 실행컨텍스트 안에 있는 환경레코드에 새로운 식별자 TV Chaannel을 기록합니다.
그리고 var 키워드로 선언해서 undefined로 값을 초기화 해둡니다.

이렇게 실행하기전에 스캔하고 준비하는 단계를 생성 단계 라고 합니다
생성 단계 Creation Phase
실행하기전에 스캔하고 준비하는 단계
- Execution Context 생성
- 선언문만 실행해서 환경 레코드에 미리 기록
그리고 선언문 외에 코드를 단계적으로 실행하는 것을 실행 단계라고 합니다.
실행 단계 Execution Phase
- 선언문 외 나머지 코드 순차적 실행
- 환경 레코드 참조하거나 업데이트 함
실행 과정을 살펴보겠습니다.

출력하려면 TVChannel에 바인딩 된 값이 뭔지 알아야 함
js 엔진은 현재 활성화된 실행컨텍스트 내에 환경 레코드를 보고 이미 기록된 TV Channel 의 값을 참조해서
오류 없이 미리 값을 출력합니다.

사실 콘솔로그도 함수기 때문에 콘솔로그를 호출하면,
이 함수의 실행컨텍스트가 생기는게 맞지만 깍두기라고 생각합시다.
그 다음라인을 실행하는데 선언은 아까 생성단계에서 이미 했으니

이 라인의 할당만 실행한다.
TV Channel 에 바인딩된 값을 netflix로 업데이트해서 기록해둡니다.

이제 마지막 콘솔로그를 실행하면!
js 엔진은 역시 환경레코드를 참조해서 TV Channel의 값을 netflix로 결정해냅니다.
만약 var 키워드 대신 ES6에서 추가된
Q. const 키워드로 변수를 선언하면?

이 경우 엔진이 TV Channel 식별자를 기록해두긴 하지만, 값을 초기화 하지 않아요
따라서 선언문이전에 TV Channel 을 참조하려고 하면! Reference Error가 발생합니다.
일시적 사각지대 Temporal Dead Zone
let, const로 선언했을 때, 선언 이전에 식별자를 참조할 수 없는 구역

var 키워드
로 선언할때에는 선언과 초기화가 동시에 이루어집니다.
선언 Declaration
메모리 공간 확보하고, 그 공간에 식별자와 연결

초기화 Initialization
식별자에 암묵적으로 undefined 값 바인딩 (초기화)

let, const 키워드
로 선언을 하면 선언부는 똑같지만, 값을 undefined로 초기화 xxxx
선언 Declaration
메모리 공간을 확보하고, 그 공간을 식별자와 연결

초기화 Initialization
자연스럽게 할당문 직전까지 변수에 아무런 값이 담기지 않습니다. => 일시적 사각지대
'언어 차원에서 보완된 점'
Fuction Hoisting 함수 호이스팅