반응형
실행 컨텍스트란?
- 실행할 코드에 제공할 환경 정보들을 모아놓은 객체.
- 동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장.
- 이때 하나의 실행 컨텍스트를 구성하는 방법(동일한 환경을 구성)은
- 전역 공간
- eval() 함수
- 함수가 있음.
이때, 자동으로 생성되는 전역 공간과 사용하는 것을 추천하지 않는 eval을 제외하면 우리가 흔히 실행 컨텍스트를 구성하는 방법은 함수를 실행하는 것임.
실행 컨텍스트에 담기는 정보
VariableEnvironment
- 여기에 담기는 내용은 LexicalEnvironment와 같지만 최초 실행 시의 스냅샷을 유지한다는 점이 다름.
(실행 컨텍스르 생성시 초기 상태를 유지함) - 실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음, 이를 그대로 복사해서 LexicalEnvironment를 만들고, 이후에 LexicalEnvironment를 주로 활용함.
LexicalEnvironment
- 자바스크립트 코드에서 변수나 함수 등의 식별자를 정의하는데 사용하는 객체.
- VariableEnvironment와 달리 함수 실행 도중에 변경되는 사항이 즉시 반영됨.
- 식별자와 참조 혹은 값을 기록하는 Environment Record와 outerEnvironmentReference 라는 또 다른 Lexical Environment를 참조하는 포인터로 구성된다.
- outerEnvironmentReference 는 외부 Lexical Environment를 참조하는 포인터로, 중첩된 자바스크립트 코드에서 스코프 탐색을 하기 위해 사용한다.EnvironmentRecord
- 현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장됨.
- 컨텍스트를 구성하는 함수에 지정됨 매개변수 식별자, 선언한 함수가 있을 경우 그 함수 자체, var로 선언된 변수의 식별자 등이 식별자에 해당함.
- 컨텍스트 내부 전체를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집 함. (호이스팅)
호이스팅- 변수 정보를 수집하는 과정은 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드들은 실행되기 전의 상태 ⇒ 코드가 실행되기 전임에도 불구하고 자바스크립트 엔진은 이미 해당 환경에 속한 코드의 변수명들을 모두 알고 있음
- 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음 실제 코드를 실행한다 해도 코드를 해석하는데 문제가 없을 것 ⇒ 호이스팅
- 호이스팅 ⇒ 변수 정보를 수집하는 과정을 더욱 이해하기 쉬운 방법으로 대체한 가상의 개념 (자바스크립트 엔진이 실제로 끌어올리지는 않음)
- 샘플 코드 (호이스팅 전)
function a() { var x = 1; // 매개변수 console.log(x); var x; console.log(x); var x = 2; console.log(x); } a();
- 샘플 코드 (호이스팅 진행 중 - 매개변수를 변수 선언/할당과 같다고 간주해서 변환)
function a() { var x = 1; // 매개변수 console.log(x); var x; console.log(x); var x = 2; console.log(x); } a();
- 샘플 코드(호이스팅 완료)
function a() { var x; var x; var x; x = 1; // 매개변수 console.log(x); // 1 console.log(x); // 1 x = 2; console.log(x); // 2 } a();
함수 선언문과 함수 표현식- 함수 선언문 ⇒ function 정의부만 존재하고 별도의 할당 명령이 없는 것.
function a() { // 함수 선언문 ... }
- 함수 표현식
- 정의한 function을 별도의 변수에 할당하는 것
const a = function() { // (익명) 함수 표현식 ... }
What is Difference?- 샘플 코드 (호이스팅 전)
console.log(sum(1, 2)); console.log(multiply(3, 4)); function sum(a, b) { // 함수 선언문 return a + b; } var multiply = function (a, b) { // 함수 표현식 return a * b; };
- 호이스팅 진행 후
⇒ 함수 선언문은 전체를 호이스팅 한 반면 함수 표현식은 변수 선언부만 호이스팅 함. (디버깅 하기 쉬운 이유로 함수 표현식을 사용하는 것을 추천!)스코프var sum = function sum(a, b) { return a + b; }; var multiply; console.log(sum(1, 2)); // 3 console.log(multiply(3, 4)); // multiply is not a function multiply = function (a, b) { return a * b; };
- 식별자에 대한 유효범위.
- 어떤 경계 A의 외부에서 선언한 변수는 A의 외부 뿐만 아니라, A의 내부에서도 접근이 가능하지만, A의 내부에서 선언한 변수는 오직 A의 내부에서만 접근할 수 있음.
const a = 10; function b() { console.log(a); // a에 접근할 수 있음. } function c() { const d = 10; } console.log(d); // 접근할 수 없음. 오직 c() 내부에서만 접근 가능
스코프 체인- 이러한 식별자의 유효범위를 안에서 바깥으로 차례로 검색해나가는 것.
- 스코프 체인을 가능하게 하는 것이 바로 LexcialEnvironment의 두 번째 수집 자료인 outerEnvironmentReference.
OuterEnvironmentReference- outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexcialEnviroment를 참조함.
- 예를 들어 A 함수 내부에 B 함수를 선언하고, 다시 B 함수 내부에 C 함수를 선언한 경우, 함수 C의 outerEnvironmentReference는 함수 B의 LexicalEnvironment를 참조 함. 함수 B의 LexicalEnvironment에 있는 outerEnvironmentReference는 다시 함수 B가 선언되던 때(A)의 LexicalEnvironment를 참조.
- 이러한 식으로 outerEnvironmentReference는 연결리스트 형태를 띰.
- 원할한 협업을 위해서는 전역공간에 함수를 선언하거나 동명의 함수를 중복 선언하는 경우는 없어야만 함. 그러나 만에 하나 전역공간에 동명의 함수가 여럿 존재하는 상황이라 하더라도 모든 함수가 표현식으로 정의돼 있었다면 위와 같은 상황은 일어나지 않았을 것임!!
- 각 outerEnvironmentReference는 오직 자신이 선언된 시점의 LexicalEnvironment만 참조하고 있으므로 가장 가까운 요소부터 차례대로 접근할 수 있고 다른 순서로 접근하는 것은 불가능 함 ⇒ 이러한 특징으로 여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능.
- 참고로, 전역 컨텍스트의 LexicalEnvironment까지 탐색해도 해당 변수를 찾지 못하면 undefined를 반환.
변수 은닉화
- 스코프 체인 상에 있는 변수라고 해서 무조건 접근 가능한 것은 아님.
var a = 10;
function b() {
var a = 20;
console.log(a);
// b() 내부에서 a에 접근하려고 하면 무조건 스코프 체인 상의 첫번째 인자부터 검색할 수 밖에 없음.
}
전역변수와 지역변수
- 전역공간에 선언한 변수 ⇒ 전역 변수
- 함수 내부에서 선언한 변수 ⇒ 지역 변수
- 코드의 안전성을 위해 가급적 전역변수 사용을 최소화하고자 노력하는 것이 좋다!
ThisBinding
- 실행 컨텍스트의 thisBinding에는 this로 지정된 객체가 저장됨.
- 실행 컨텍스트 활성화 당시에 this가 지정되지 않은 경우 this에는 전역 객체가 저장됨.
- 이에 관해서 자세한 내용은 다음 글에서~
OuterEnvironmentReference
반응형
'javascript & Node.js > javascript' 카테고리의 다른 글
자바스크립트 프로토타입과 클래스 (0) | 2021.01.29 |
---|---|
자바스크립트 클로저 (0) | 2021.01.28 |
자바스크립트 콜백 함수 (0) | 2021.01.26 |
자바스크립트 this (0) | 2021.01.26 |