1. 실행 컨텍스트
1. 개념
현재 실행중인 코드에 대한 세부정보(제어 흐름의 위치, 변수함수, this, arguments 등)를 저장해놓은 내부 데이터 구조.
2. 종류
(1) Global Execution Context
생성시점: 스크립트가 처음 실행될때
(2) Function Execution Context
생성시점: 함수가 호출될때
이렇게 생성된 이것들은 실행 컨텍스트 스택(==콜스택)에 저장되어 관리.
여기서 자료구조가 '스택'이라는 거에 주목하면 된다.
스크립트가 처음 실행될때 생성되는 global execution context는 스택의 가장 아랫부분에 위치하고
이 말은 곧, 프로그램이 종료되고 나서야 메모리에서 제거된다는 뜻.
cf. 재귀함수: 종료조건을 잘못 설정하여 실행 컨텍스트가 계속해서 콜스택에 push되어 쌓이게 되면 스택 오버플로우 발생할 수 있다. 조심하자. (재귀방식보다는 반복문 방식이 메모리 공간을 절약하는 방법이다.)
3. 구조
(1) 스크립트 전체
(2) 코드블록 {...}
(3) 호출된 함수
이 세개는 렉시컬 환경이라는 것을 가지고 있다.
2. 렉시컬 환경 (Lexical Environment)
렉시컬 환경은 식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료구조로 실행 컨텍스트를 구성하는 컴포넌트이다.
cf. 실행 컨텍스트 스택(콜스택)이 코드의 실행 순서를 관리한다면, 렉시컬 환경은 스코프와 식별자를 관리한다.
1. 환경 레코드 - 현재 실행중인 코드환경의 this값 및 호출된 함수에서 선언된 변수, 함수 저장
2. 외부 렉시컬 환경 - 부모환경의 렉시컬 환경 참조값을 가지고 있다. (외부변수에 접근 가능)
이렇게 두 부분으로 구성되어있다.
코드로 자세히 살펴보면,
<script>
// (A)
let name1 = 'Son'; // (B)
var name2 = 'ny';
function solution() {
let answer = 'Nice one';
console.log(`${answer} ${name1}${name2}`); // (C)
}
solution(); // (D)
</script>
위 코드에서는 총 2개의 렉시컬 환경이 존재한다.
- Global 렉시컬 환경
- 함수 solution의 렉시컬 환경
여기서 2개는 정해진 개수가 아니라, 선언된 함수의 수에 따라 프로그램은 더 많은 렉시컬 환경을 가질 수 있다.
실행 순서
1. (A) 에서 global 렉시컬 환경이 만들어진다.
2. (D)에서 solution 함수가 실행되고 solution 함수의 렉시컬 환경이 만들어진다.
3. JS 엔진이 (C) 부분에서 문자열 템플릿 리터럴 내에서 사용되는 변수들을 찾기위해 solution의 렉시컬 환경의 환경 레코드를 탐색한다.
4. answer만 존재하고 name1, name2는 찾을 수 없다.
5. 외부 렉시컬 환경의 참조를 통해 global영역의 환경 레코드에 접근한다. => name1, name2 찾음.
★ 외부 렉시컬 환경은 함수가 실행되는 시점이 아닌 선언된 시점의 외부 환경을 가리킨다는 사실이다.
let name = 'Son';
function f1() {
let name = 'Kim';
f2();
}
function f2() {
console.log(name);
}
f1();
f1()을 실행하고 나면 출력되는 값은 'Son'이다.
f1함수내에서 f2를 호출했기 때문에 'Kim'을 출력한다고 생각할 수 있겠으나,
함수가 선언된 시점의 외부 환경을 참조하므로 f2의 외부렉시컬 환경은 Global 영역이 되겠다.
그래서 스크립트 전역에 선언된 name변수를 참조하여 'Son'을 출력하는 것이다.
3. 실행 컨텍스트 생성과정
실행 컨텍스트 내부구조
1. 생성단계
- Lexical Environment가 생성된다.
- 함수
함수 선언문: 메모리에 바로 올라간다.
함수 표현식: 함수가 할당된 변수의 선언문만 호이스팅 된다. - 변수
var: 선언문이 호이스팅 되고 undefined로 초기화됨.
let,const: 선언문이 호이스팅 되고 uninitialized 상태가된다.
- 함수
- This 바인딩.
- Global: 브라우저 환경일 경우 window가 전역오브젝트로 this에 window가 할당된다.
- Function: argrument 객체가 초기화 된다. (window 할당은 없음)
3. 모든 변수가 생성 단계에서 Lexical 환경에 초기화 되기때문에 JS엔진은 변수들의 존재를 모두 미리 인지하게 되고, 이게 호이스팅이 발생하는 이유다.
2. 실행단계
생성 단계에서 결정된 Lexical 환경을 가지고 있는 상태로, 코드를 한 줄씩 실행해 나간다.
그 과정에서 변수에 값을 할당하면 렉시컬 환경의 해당 변수 값이 변경된다.
=> 실행 컨텍스트는 이렇게 두 단계에 걸쳐 생성되어 코드 흐름에 따라 콜스택에 관리 된다.
cf. 함수 코드 평가 순서
함수가 호출되면 전역 공간에 있던 코드의 제어권이 함수의 내부로 이동하면서 함수 코드를 평가하게 되는데,
다음과 같은 순서로 함수코드를 평가한다.
① 함수 실행 컨텍스트 생성
② 함수 Lexical Environment 생성
2-1) 함수 environment 레코드 생성
2-2) this 바인딩
2-3) 외부 렉시컬 environment에 대한 참조 결정
'Frontend > Javascript' 카테고리의 다른 글
[Javascript] 함수선언문 vs 함수표현식 (0) | 2023.08.11 |
---|---|
[Javascript] var, let, const의 차이(cf. 스코프, 호이스팅) (0) | 2023.08.11 |
[Javascript] 스코프 (0) | 2023.08.09 |
[Javascript] Javascript와 ES6 (0) | 2023.08.08 |
[Javascript] 클로저 (0) | 2023.07.06 |