PracticeEveryday
JavaScript 본문
실행 컨텍스트
- 실행할 코드에 제공할 환경 정보들을 모아 놓은 객체
- 자바스크립트의 동적 언어로서의 성격을 가장 잘 파악할 수 있는 개념
자바스크립트는 실행 컨텍스트가 활성화 되는 시점에 다음과 같은 현상이 발생한다.
- 호이스팅이 발생한다 ( 선언된 변수를 위로 끌어 올린다. )
- 외부 환경 정보를 구성한다.
- this 값을 설정한다.
실행 컨텍스트 구성
- 실행 컨텍스트는 다음과 같은 것들을 이용하면 call stack에 쌓이게 된다.
- 전역 공간은 자동으로 컨텍스트로 구성된다.
- 함수를 실행한다.
- eval() 함수를 만든다.
- block을 만든다.
// 일반적으로 함수를 이용한 실행 컨텍스트를 사용한다.
var a = 1; // 전역 컨텍스트
function outer() {
// outer context
function inner() {
// inner c
console.log(a); // 3
var a = 3;
console.log(a); // 1
}
inner();
console.log(a); // 1
}
outer();
console.log(a);
- 위와 같은 코드를 구성했을 때 실행 컨텍스트의 스택은 다음과 같은 순서로 실행된다.
- 프로그램 실행 : 전역 컨텍스트
- outer 실행 : 전역 컨텍스트 ,outer
- inner 실행 : 전역 컨텍스트, outer, inner
- inner 종료 : 전역 컨텍스트, outer
- outer 종료 : 전역 컨텍스트
※ 실행 컨텍스트를 구성할 때 생기는 것들
1. VariableEnvironment
- 현재 컨텍스트 내의 식별자(변수)들에 대한 정보
- 외부 환경 정보
- 선언 시점의 LexicalEnvironment의 스냅샷 ( 변경 사항 반영 x )
2. LexicalEnvironment
- 처음에는 VariableEnvironment와 같음
- 변경 사항이 실시간으로 반영됨
3. ThisBinding
- 식별자가 바라봐야 할 대상 객체
Variable: 변수 Environment
- VariableEnvironment에 담기는 내용은 LexicalEnvironment와 같지만, 최초 실행 시의 스냅샷을 유지한다.
- 실행 컨텍스트를 생성할 때 VariableEnvironment에 정보를 먼저 담은 다음, 이를 복사해서 LexicalEnvironment를
만든다.
주로 활용하는 것은 LexicalEnvironment이다. 즉, VariableEnviroment는 스냅샷 유지를 목적으로 사용한다.
Lexical Environment
- LexicalEnvironment의 내부에는 environmentRecord와 outerEnvironmentReference로 구성돼 있다.
- environmentRecord로 인하여 호이스팅이 발생한다.
- outerEnvironmentReference로 인하여 스코프와 스코프체인이 형성된다.
environmentRecord와 Hoisting( 호이스팅 )
- 자바스크리트는 코드를 실행하기 전에 식별자를 수집한다.
EnvironmentRecord
현재 컨텍스트와 관련된 코드의 식별자 정보들이 저장된다.
매개변수 식별자
함수 자체
함수 내부의 식별자
Host Object( 호스트 객체 )
전역 실행 컨텍스트는 변수 객체를 생성하는 대신 전역 객체를 활용한다.
브라우저의 Window 객체, Node의 Global 객체 등이 이에 해당된다.
이들은 Host Object로 분류된다.
=> 즉 코드가 실행되기 전에 자바스크립트의 엔진은 이미 실행 컨텍스트에 속한 변수명을 모두 알고 있게 되는 셈이다.
// 이때 호이스팅이란 개념이 이용된다.
- 엔진의 실제 동작 방식 대신에 자바스크립트 엔진은 식별자들을 최상단으로 끌어올려놓은 다음, 실제 코드를
실행한다. 라고 생각해도 코드 해석에 문제되는 것이 없기 때문이다.
=> 중요한 점은 자바스크립트 엔진이 실제로 변수를 끌어올리지는 않지만, 편의상 끌어올리는 것으로 간주하자는
것이다.
변수의 호이스팅
function func(x) {
console.log(x); // 1
var x;
console.log(x); // 1
var x = 2;
console.log(x); // 2
}
func(1);
위 코드는 다음과 같이 해석될 수 있다.
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 a() {
console.log(b); // function b
var b = "bbb";
console.log(b); // bbb
function b() {}
console.log(b); // bbb
}
a();
변수의 경우 정의부만 호이스팅 되지만, 함수는 함수 전체가 호이스팅 된다.
function a() {
var b;
function b() {}
console.log(b); // function b
b = "bbb";
console.log(b); // bbb
console.log(b); // bbb
}
a();
자바스크립트의 함수는 일급객체 (or 일급시민) 이기에 함수 표현식이 가능하다.
일급객체(일급시민)
여기 x라는 것이 있다.
- x를 변수에 담을 수 있다.
- x를 매개변수에 넘길 수 있다.
- x를 함수에서 반환할 수 있다.
x를 만족할 때, 이를 일급객체라고 한다.
즉, 자바스크립트의 함수는 일급객체이므로
- 함수를 변수에 담을 수 있다.
- 함수를 매개변수로 넘길 수 있다.
- 함수를 함수에서 반환할 수 있다.
위의 같은 조건을 만족한다.
function a() {
console.log(b); // undefined
var b = "bbb";
console.log(b); // bbb
var b = function () {}; // b에 익명함수를 할당했다.
console.log(b); // function b
}
a();
위의 코드는 아래와 같다.
function a() {
var b;
var b;
console.log(b); // undefined
b = "bbb";
console.log(b); // bbb
b = function () {}; // b에 익명함수를 할당했다.
console.log(b); // f () {}
}
a();
outerEnvironmentReference와 Scope
scope
스코프란 식별자에 대한 유효범위이다.
Scope A의 외부에서 선언한 변수는, A의 외부/ 내부 모두 접근 가능하다.
A의 내부에서 선언한 변수는 오직 A의 내부에서만 접근 할 수 있다.
스코프의 개념은 대부분의 언어에서 존재하지만, ES5까지의 JavaScript는 오직 함수에 의해서만 스코프가 생성된다.
Scope Chain
식별자의 유효범위를 안에서 바깥으로 차례로 검색해나가는 것
이를 가능하게 하는 것이 outerEnvironmentReference이다.
- outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 LexicalEnvironment를 참조한다.
- 선언하다라는 행위가 실제로 일어날 수 있는 시점은 콜 스택 상태에서 어떤 실행 컨텍스트가 활성화 된 상태뿐이다.
모든 코드는 실행 컨텍스트가 활성화 상태일 때 실행되기 때문이다.
var a = 1; // 전역 컨텍스트
function outer() {
// outer 컨텍스트
function inner() {
// inner 컨텍스트
console.log("1 :", a); // 1: undefined
var a = 3;
console.log("2 :", a); // 2 : 3
}
inner();
// inner가 실행될 때 outer의 LexcicalEnvironemnt를 outerEnvironmentReference로 참조한다.
console.log("3 :", a); // 3: 1
}
outer();
// outer가 실행될 때 전역 컨텍스트의 LexcicalEnvironemnt를 outerEnvironmentReference로 참조한다.
console.log("4 :", a); // 4: 1
위 코드의 scope chain은 아래와 같다.
inner LexicalEnvironment {
식별자 a
outerEnvironmentReference = outer LexicalEnvironment {
식별자 a
outerEnvironmentReference = global LexicalEnvironment {
식별자 a
}
}
}
}
이와 같은 구조적 특성 덕분에 여러 스코프에서 동일한 식별자를 선언할 경우,
무조건 Scope Chain 상에서 가장 먼저 발견된 식별자에만 접근 가능 하게 된다.
inner LexicalEnvironment {
식별자 a # inner function에서 a에 접근할 때 여기에 가장 먼저 접근
outerEnvironmentReference = outer LexicalEnvironment {
식별자 a # outer function에서 a에 접근할 때 여기에 가장 먼저 접근
식별자 b # inner function에서 b에 접근할 때 여기에 가장 먼저 접근
outerEnvironmentReference = global LexicalEnvironment {
식별자 a # 전역에서 a에 접근할 때 여기에 가장 먼저 접근
식별자 b # 전역에서 b에 접근할 때 여기에 가장 먼저 접근
식별자 c # inner function에서 c에 접근할 때 여기에 가장 먼저 접근
}
}
}
}
실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다
- 전역 공간에서 자동으로 생성되는 전역 컨텍스느
- eval 함수
- 함수 실행에 의한 컨텍스트
실행 컨텍스트 객체는 활성화 되는 시점에 VariableEnvironment, LexicalEnvironment, ThisBinding의 세가지 정보를 수집한다.
실행 컨텍스트를 생성할 때 VariableEnvironment와 LexicalEnvironment가 동일한 내용으로 구성된다.
LexicalEnvironment는 함수 실행 도중에 변경되는 사항이 즉시 반영된다.
LexicalEnvironment와 VariableEnvironment는 environmentRecord와 outerEnvironmentReference로 구성되어 있다.
- 이것 때문에 hoisting이란 개념이 사용된다.
- 호이스팅은 코드 해성을 좀 더 수월하게 하기 위해 environmentRecord의 수집 과정을 추상화한 개념이다.
- 변수 선언부와 함수 선언문에 호이스팅이 발생한다.
- 함수 표현식을 사용할 경우 함수의 선언부만 호이스팅이 발생한다.
outerEnvironmentReference는 상위(직전)) 컨텍스트의 LexicalEnvironment 정보를 참조한다.
- 이것 때문에 scope가 형성되고 스코프 체인을 통해 상위 컨텍스트에 접근할 수 있다.
- 스코프는 변수의 유효범위를 이야기한다.
자바스크립트 실행 컨텍스트 | 개발자 황준일
자바스크립트 실행 컨텍스트 실행 컨텍스트는 자바스크립트에서 가장 중요한 핵심 개념 중에 하나다. 이를 정확히 이해하는 것은 자바스크립트 개발자에게 매우 중요하다. 1. 개념 실행 컨텍스
junilhwang.github.io
'JavaScript' 카테고리의 다른 글
JavaScript (0) | 2022.06.02 |
---|---|
JavaScript (0) | 2022.05.25 |
JavaScript (0) | 2022.05.18 |
JavaScript (0) | 2022.05.18 |
JavaScript (0) | 2022.05.18 |