엔진은 너의 코드를 어떻게 읽는가?
in what order you think the browser will evaluate that code?
의사 표현은 내가 어떻게 하느냐 따라 결과가 달라진다. 내 위주로 전달하는 말과 상대방이 이해할 수 있을까 고민한 뒤 전달하는 말은, 처음 품었던 의도는 같을지언정 그 결과가 천차만별이다.
자바스크립트는 코드를 이해하는 나름의 원칙이 있다. 코드를 실행하기 전에 무언가를 생성한다는 것. 그게 뭘까?
Execution Context
Execution Context 는 자바스크립트의 핵심 개념으로,코드를 실행하기 위해 필요한 환경
환경 정보들을 모아놓은 객체
동적 언어
javascript는 어떤 execution context
가 활성화되는 시점에 선언된 변수들을 위로 끌어올리고(hoisting
), 외부 환경 정보를 구성하고, this
값을 설정하는 등의 동작을 수행하는데, 이로 인해 다른 언어에서는 발생할 수 없는 특이한 현상들이 발생한다.
자바스크립트의 주요한 실행 컨텍스트에는 두 가지가 있다.
1. Global Execution Context
디폴트 전역 실행 컨텍스트로, 자바스크립트 파일이 엔진에 의해 처음 로드되었을 때 실행되기 시작하는 환경이다.
2. Fuction Execution Context
우리가 execution context를 따로 구성하는 방법은 함수를 실행하는 것 뿐이다. 함수가 호출되고 실행됨에 따라서 해당 함수 안에서 생성되는 컨텍스트. 각각의 함수는 고유의 실행 컨텍스트를 가진다. 그리고 전역 실행 컨텍스트에 언제나 접근할 수 있다.
예제 : 평범한 함수 호출
// (1)const a = "hello world!";
const bar = () => {// (5)console.log(a)
};// (6)const foo = ()=>{// (3)
bar()// (4)
};// (7)
foo();// (2)// (8)

- Global Execution Context 생성.
자바스크립트 파일이 열리는 순간(별도의 명령 없이) 전역 실행 컨텍스트가 생성된다. 그리고 global execution context가 가장 먼저 callstack에 push된다. 지금
callstack
의 맨 위에는 global execution이 있으므로 자바스크립트 엔진은 이제 전역 실행 컨텍스트 상에서 코드를 읽어내려가기 시작한다.
- foo 호출
foo함수를 호출할 때, Global Execution Context는 멈춘다. 왜냐하면 자바스크립트는 싱글 스레드 환경이기 때문에, 한 번에 하나의 코드만을 실행할 수 있기 때문이다.
- push
자바스크립트 엔진은 foo함수에 대한 환경 정보를 수집해서 foo execution context를 생성한 후,
callstack
에 push한다. 이제 함수 내부의 코드들이 순서대로 진행된다.
- bar함수 호출.
foo함수의 Execution Context는 멈춘다.
- bar함수의 Execution Context가 생성되고
callstack
에 push된다. 읽어내려간다. console.log함수를 실행한다. 전역 변수인 a의 값이 콘솔창에 뜸으로써 console.log함수의 실행이 끝난다.
- 더 읽어내려갈 게 없으므로 bar함수의 Execution Context가 종료된다.
callstack
에서 pop-out된다. 그리고 해당 함수 바로 밑의 Execution Context, 여기에선 foo함수의 Execution Context가 계속된다.
- 더 읽어내려갈 게 없으므로 foo함수의 Execution Context가 끝난다.
- 더 읽어내려갈 게 없으므로 Global Execution Context가 끝난다.
callstack
call은 호출을 뜻한다. stack은 출입구가 하나뿐인 깊은 우물 같은 데이터 구조다.
따라서 callstack
은 자바스크립트가 함수 호출을 기록하기 위해 사용하는 우물 형태의 데이터 구조이다.
항상 맨 위에 놓인 함수를 우선으로 실행된다. 이런 식으로 자바스크립트 엔진은 가장 위에 쌓여있는 context와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다.
자바스크립트가 동기적(synchronous) 언어라는 것의 의미
Javascript engine needs to keep track of what’s happening.
함수, 인자값, 변수들은 callstack
에 push되어 하나의 stack frame을 이룬다. stack frame
은 stack에서 메모리가 위치하는 곳이다. 함수가 어떠한 값을 return함으로써 stack상에서 pop out되면 메모리는 사라진다.(return은 함수의 output값을 내뱉는다는 뜻이다. 그리고 함수의 기능은 어떤 인풋에 대해 특정한 아웃풋을 내뱉는 것이 그 기능이다. 즉, return
을 한다는 것은 그 즉시 함수의 아웃풋 값을 내뱉고 실행을 종료시킨다는 의미이다. 함수가 명시적으로 값을 return하지 않더라도, 모든 함수는 디폴트로 undefined를 return한다. )
The call stack maintains a record of the position of each stack frame.It knows the next function to be executed synchronous
한마디로, 자바스크립트 엔진은 모든 걸 실행하기 전에 전체 코드를 훑어본 뒤, 고정된 스케줄을 미리 짜놓는다.
execution context는 어떤 정보를 수집할까?
1. VariableEnvironment
현재 컨텍스트 내의 식별자들에 대한 정보와 외부 환경 정보.
최초 실행 시의 스냅샷을 유지한다. 변경 사항은 반영되지 않음.
실행 컨텍스트를 생성할 때 VariableEnvironment
에 정보들을 먼저 담은 다음,
이를 그대로 복사해서 LexicalEnvironment
를 만들고 주로 후자를 쓰게 된다.
initialize과정중에는 사실상 완전히 동일하고 이후 코드 진행에 따라 달라진다.
2. LexicalEnvironment
백과사전 같은 개념. "현재 컨텍스트의 내부에는 a,b,c와 같은 식별자들이 있고
그 외부 정보는 D를 참조하도록 구성되어 있다."라는 환경 정보들.
둘은 대게 동일한 값을 갖는다. 그러나 만들어진 변수 선언 및 함수 선언에 대해 바인딩을 유지한다.
LexicalEnvironment
는 코드 실행 중에 실행 컨텍스트 내에서 변경될 수 있지만VariableEnvironment
는 항상 값을 유지한다.LexicalEnvironment
는 일시적으로LexicalEnvironment
하위에 새로운 환경을 가리킵니다.
- 이 새로운 환경은 임시 바인딩을 보유합니다.
- 그리고 임시 범위를 벗어나면
VariableEnvironment
가 참조하고 있는 값으로LexicalEnvironment
를 복구합니다.
둘 모두 내부는 environmentRecord
와 outer-environmentReference
로 구성.
Outer Environment Reference
- 중첩 유효 범위를 가질 수 있는 환경에서 상위
Lexical Environment
를 참조한다.
- 즉, 외부 환경에 대한 참조를 가지고 있다.
- 전역 환경에서는 null이다.
- 중첩 유효 범위를 가질 수 있는 환경에서 상위
Environment Record
- 유효범위 내의 값에 식별자를 매핑한다.
- 변수 선언 및 함수 선언을 저장한다.
추가 질문.
1. environmentRecord 에는 구체적으로 무엇이 담기는가?
2. scope와 scope chain
3. 싱글 스레드란?
4. asynchronous란?
5. call stack과 event loop
이 포스트는 코어 자바스크립트
책과 밑의 글을 토대로 쓰여졌습니다.
hackernoon.com/javascript-execution-context-and-lexical-environment-explained-528351703922
JavaScript Execution Context and Lexical Environment Explained. | Hacker Noon JavaScript Execution Context and Lexical Environment Explained. Photo by Shane Rounce on Unsplash As a JavaScript Programmer have you ever wondered how JavaScript engine executes your code when its run inside the browser? And how they keeps track the loca hackernoon.com
iamsjy17.github.io/javascript/2019/06/10/js33_execution_context.html
Songlog Javascript, Typescript, Angular, React, RxJS, etc. iamsjy17.github.io
'language' 카테고리의 다른 글
제어자 (modifier) (0) | 2023.03.24 |
---|---|
OOP (0) | 2023.03.24 |
c언어. 구조체 (0) | 2022.12.21 |
c언어. 포인터와 주솟값 (0) | 2022.12.20 |
JS 스코프와 scope chain (0) | 2022.12.03 |