실행컨텍스트 질문 리스트
해당하는 질문들을 대답할 수 있도록, 본인이 공부한 흐름에 맞게 정리하여 올려주세요.
실행 컨텍스트는 어떤 정보가 담겨 있는가?
호이스팅 (Hoisting)란 무엇인가요?
scope란 무엇이며 var, let, const에 대해 설명해주세요.
스코프 체인은 무엇인가?
인수 실행컨텍스트
흐름
실행컨텍스트란
> 실행컨텍스트 구성요소
> EnvironmentRecord와 호이스팅
> outerEnvironmentReference와 스코프체인
1. 실행컨텍스트란?
1.1 정의
- 실행컨텍스트는 “실행할 코드에 제공할 환경정보들을 모아놓은 객체" 이다.
- 실행컨텍스트는 생성 시 “콜스택”에 쌓아올려지고, 콜스택 최상단 컨텍스트의 코드들을 실행하는 방식으로 “전체코드의 환경과 순서를 보장”한다.
1.2 생성시점
- 실행컨텍스트는 4가지 방법을 통해 생성될 수 있다.
전역컨텍스트
는 자동으로 생성된다.함수
실행 시eval()
함수 실행 시- ES6+의
block
생성 시()
- 실행컨텍스트가 생성(활성화) 되는 시점에서 발생하는 일
- 선언된 변수들을 끌어 올린다.
호이스팅
- 외부 환경 정보 구성 (
LexicalEnvironment의 OuterEnvironmentReference
) - this의 값을 설정
2. 실행컨텍스트 구성요소
실행컨텍스트 구성요소
VariableEnvironment : environmentRecord + outerEnvironment (
스냅샷
)
LexicalEnvironment : environmentRecord + outerEnvironment
ThisBinding2.1 VariableEnvironment
- 실행컨텍스트 생성 시 가장 먼저 생성됨
- EnvironmentRecord + OuterEnvironmentReference
- 생성 이후, 그대로 복사하여 LexicalEnvironment 를 생성
- 최초 실행 시의 정보만을 가지고, 이후에 변화된 정보를 담아내지 못함
스냅샷
- *실제 JS엔진에서는 VariableEnvironment보다 LexicalEnvironment를 주로 활용함
2.2 LexicalEnvironment
현재 컨텍스트의 내부 식별자 정보 (EnvironmentRecord)와
외부 컨텍스트의 정보 (OuterEnvironmentReference)를 가지고 있음
- 첫 생성 시는 VariableEnvironment와 같음
- EnvironmentRecord + OuterEnvironmentReference
- 변경사항이 실시간으로 즉각 반영됨
- EnviromentRecord로 인하여 호이스팅이 발생한다.
- OuterEnvironmentReference로 인하여 스코프와 스코프체인이 형성된다.
2.3 This
- 별도 포스팅
3. EnvironmentRecord와 호이스팅
3.1 호이스팅 이란
- EnvironmentRecord에는 현재 컨텍스트와 관련된 코드의 “식별자 정보”들이 저장된다.
- 함수의 매개변수 식별자(arguments)
- 함수 선언 시, 함수 그 자체
- 변수의 식별자 (var, let, const)
- EnvironmentRecord가 생성이 완료되는 시점은, 실제 코드가 실행되기 이전이다.
- 코드가 실행 하기 전, “js엔진은 식별자들을 최상단으로 끌어올려 놓은 다음 실제 코드를 실행”하게 됨
- 이를 가상의 개념인 호이스팅이라고 지칭함
- 실제로 끌어올리지는 않지만, 그런 것 같이 동작하므로, 끌어올린 것으로 간주하는 것
3.2 사례를 통해 호이스팅 이해/점검하기
- [1번 예제]
function a(x){ console.log(x); // (1) var x; console.log(x); // (2) var x = 2; console.log(x) // (3) } a(1);
답안 및 풀이
(1): 1 (2): 1 (3) 2
- 매개 변수는 호이스팅 이전, 최상단에서 선언/할당하는 것과 같이 동작한다.
function a(x){ var x = 1; ... } a(1)
function a(x){ var x var x var x x = 1; console.log(x) // (1) 1 console.log(x) // (2) 1 x = 2; console.log(x) // (3) 2 } a(1)
4. Scope와 스코프체인, OuterEnvironmentReference
4.1 스코프, 스코프체인 이란
- 스코프는 “식별자에 대한 유효범위”
- 스코프체인이란 ”식별자에 대한 유효범위(
스코프
)를 안에서 부터 바깥으로 차례대로 검색해나가는 것”
- 스코프체인을 가능하게 하는 것은 LexicalEnvironment의 OuterEnviromentReference 이다.
4.2 OuterEnvironmentReference
- OuterEnvironmentReference는 현재 호출된 함수가 “선언된 순간”의 LexicalEnvironment를 참조한다.
선언하다
라는 행위가 실제로 일어날 수 있는 시점은 콜 스택 상에서 어떤 실행 컨텍스트가 활성화된 상태일 때뿐이다. 모든 코드는 실행 컨텍스트가 활성화 상태일 때 실행되기 때문이다.- 선언된 순간의 LexicalEnvironment는 현재 호출된 함수를 기준으로 바로 위의 컨텍스트의 LexicalEnvironment를 의미한다.
- 내부 함수에서는 외부함수의 스코프에 접근할 수 있으나, 외부함수에서는 내부 함수의 스코프에 접근할 수 없다.
- 여러 스코프에서 동일한 식별자를 선언할 경우, 무조건 해당 scope chain에서 가장 먼저 발견된 식별자에만 접근할 수 있게 된다.
- 전역에도 a 식별자가 존재하지만, inner함수에서는 inner 컨텍스트의 식별자 a에만 접근가능하다.
4.3 사례를 통해 이해/점검하기
- 예제
var a = 1; // (0) 전역 컨텍스트 var outer = function (){ // (2) var inner = function (){ // (4) console.log(a); // (5) var a = 3; // (6) } inner(); // (3) inner가 실행될 때, outer의 LexicalEnvironment를 inner컨텍스트의 outerEnvironmentReference로 참조하게 된다. console.log(a); // (7) } outer(); // (1) console.log(a); // (8)
- (0) 전역 컨텍스트 생성
- 호이스팅을 통해 environmentRecord에
{ a, outer }
식별자 정보를 저장
- (1) ⇒ (2) outer 컨텍스트 생성
- outer함수가 호출
(1)
- outer 컨텍스트의 environmentRecord에
{ inner }
식별자 정보가 저장 - outer 컨텍스트의 outerEnvironmentReference에 outer함수 선언된 순간의 컨텍스트인 전역컨텍스트의 LexicalEnvironment인
[전역, { a , outer }]
가 저장된다. - outer컨텍스트의 outerEnvironmentReference =
[전역컨텍스트, { a, outer }]
- (3) ⇒ (4) inner 컨텍스트 생성
- inner 함수가 호출
(3)
- inner 컨텍스트의 environmentRecord에
{ a }
식별자 정보가 저장 - inner 컨텍스트의 outerEnvironmentReference =
[ outer, { inner } ]
정보가 저장
- (5) console.log(a)
- 현재 컨텍스트인 inner 컨텍스트의 envirionmentRecord에서 a를 찾아 반환하게 됨
- 할당된 값이 없으므로 “
undefined
출력”
- (6) var a = 3
- inner 스코프에 존재하는 변수 a에 3을 할당
- inner 컨텍스트가 종료 되고, 다시 outer컨텍스트의 코드가 마저 실행 됨
- (7) console.log(a)
- outer 컨텍스트의 environmentRecord에서 a를 탐색 ⇒ 없음
- outer 컨텍스트의 outerEnvironmentReference의 environmentRecord 에서 a 탐색 ⇒ 전역스코프의 a 반환
- 전역 스코프의 a의 할당 값인 1이 반환
- outer컨텍스트 종료
- (8) console.log(a)
- 전역 컨텍스트의 environmentRecord에서 a를 탐색 ⇒ 발견 후 할당된 값인 1을 반환
5. 질문에 대하여 간단하게 답해보기
5.1 실행 컨텍스트는 어떤 정보가 담겨 있는가?
- 실행컨텍스트에는 해당 컨텍스트의 코드를 실행하기 위해 필요한 환경정보가 담겨있습니다.
- 실행컨텍스트 생성 시점에서의 환경정보를 스냅샷처럼 가지고 있는 VariableEnvironment와 실행컨텍스트 생성 이후 환경정보의 변화를 즉각적으로 반영하는 LexicalEnvironment 그리고, 함수 호출에 따라 달라지는 this를 가지고 있습니다.
- 조금 더 구체적으로, LexicalEnvironment는 해당 컨텍스트의 식별자 정보 모음인 EnvironmentRecord와 해당 컨텍스트의 바로 상위 컨텍스트의 LexicalEnvironment를 참조하고 있는outerEnvironmentReference를 가지고 있습니다.
5.2 호이스팅 (Hoisting)란 무엇인가요?
호이스팅은 컨텍스트가 생성되는 시점에서, 컨텍스트 내부의 식별자들이 끌어올려지듯이 동작하여 먼저 선언되는 현상을 말합니다.
- 코드가 실행 하기 전, “js엔진이 해당 컨텍스트의 식별자들을 최상단으로 끌어올려 놓은 다음 실제 코드를 실행”하는 것 처럼 동작하는 것을 나타내는 가상의 개념입니다.
- 이는 실행컨텍스트 생성 시, EnvironmentRecord에 식별자정보를 저장하는 과정에서 발생합니다.
- 직관적인 코드이해와 다른 결과를 나타낼 수 있으므로, 주의가 필요합니다.
5.3 scope란 무엇이며 var, let, const에 대해 설명해주세요.
- 스코프는 ‘식별자의 유효범위’ 를 뜻합니다.
- var, let, const 는 모두 변수를 선언하기 위한 키워드입니다.
- var의 경우 함수스코프를 가지고, let과 const는 블록스코프를 가집니다.
- 또 var의 경우 선언과 초기화 단계가 런타임 이전에 진행되고, let과 const는 런타임이전에 선언단계만 진행됩니다.
- 따라서 실제 스코프 시작지점 부터, let, const 키워드 이전까지에서 해당 식별자의 접근이 불가하다는 특징을 가집니다. (
TDZ
) - let은 선언과 초기화, 할당을 분리할 수 있지만, const는 선언과 초기화, 할당이 동시에 이루어지고, 재할당이 불가능하다는 특징이 있습니다.
5.4 스코프 체인은 무엇인가?
스코프 체인
은 ‘식별자의 유효범위’를 내부에서 외부로 차례대로 검색해나가는 방식을 뜻합니다.
- js에서는 실행컨텍스트 생성 시, 바로 위의 실행컨텍스트의 LexicalEnvironment 정보를 outerEnvironmentReference의 참조값으로 등록함으로써, 스코프체인을 가능하도록 동작 합니다.
** This와 Closer는 별도의 포스팅으로
⇒ Go This
⇒ Go Closer
참고
- 코어자바스크립트
수경 실행컨텍스트
실행 컨텍스트란?
실행 컨텍스트는 자바스크립트 코드를 실행할 때 필요한 정보들을 저장하고 제공하는 환경이다. 즉, 스코프의 정보를 담은 환경을 의미한다.
현재 실행되고 있는 컨텍스트에서 이 컨텍스트와 관련이 없는 코드가 실행된다면 새로운 컨텍스트가 생성되어 제어권을 간다. 그리고 이렇게 생성된 컨텍스트들은 실행 컨텍스트 스택 안에 쌓이게 된다. 각각의 컨텍스트는 실행이 종료된 이후 소멸되며, 소멸된 후 이전의 실행 컨텍스트에 제어권을 넘겨주게 된다.
[실행 컨텍스트의 구성 요소]
실행 컨텍스트는 Lexical Environment와 Variable Environment 두가지 컴포넌트로 구성된다. 그리고 이 컴포넌트들은 Environment Records라 불리는 형태로 구성되어 있다.
ES2015부터 변경사항
- ES5에서는 실행 컨텍스트에 this바인딩 정보가 별도로 저장되었지만 ES2015부터는 EnvorinmentRecords에서 this바인딩에 대한 정보를 저장
- 기존 ES2015에서는 Lexical Environment: ER + LE 로 저장되어있었지만 현재 명세에서는 EnvironmentRecords에서 식별자, this 바인딩, 상위 ER에 대한 참조까지 저장
- LE와 VE가 ER 자체를 바인딩 하는 형태로 변경됨
예시
function foo() { let a = 1; const b = 2; var c = 3; console.log(a + b + c); } foo();

foo 실행 컨텍스트의 LE와 VE는 foo함수 호출에 대한 정보를 담고 있다. 선언한 식별자와 this바인딩 그리고 상위 스코프인 전역 실행 컨텍스트의 GlobalER을 참조하는 외부 환경 레코드에 대한 정보를 갖는다.
[Environment Records와 스코프 체인]
ER은 렉시컬 스코프를 기반으로 특정 변수와 함수에 대한 식별자의 연결 정보를 저장한다. 모든 ER에는
OuterEnv
필드가 있으며, 이 필드는 상위 스코프에 대한 ER을 참조한다.** 스코프 체인이란 용어는 ES3이후로 사용하지 않는 용어, 그렇지만 직관적인 이해를 돕기 위해서 자주 사용되는 듯 함. Lexical Environment 개념이 도입된 이후 ECMAScript에는
lexical nesting structure
용어를 사용[Environment Records의 하위 ER]
- declarative Environment Record - 변수, 상수, 모듈, 클래스 등 렉시컬 스코프 내에 선언된 식별자들을 바인딩
- function Environment Record
- 함수에서 사용되는 this값과 new.target에 대한 정보를 가진다. 화살표 함수가 아닌 경우에만 this를 바인딩하며, super로 상위 클래스에 대한 정보를 바인딩한다.
- module Environment Record
- 모듈의 외부 스코프를 나타내는 정보를 추가적으로 바인딩한다. 다른 ER에 존재하는 식별자에 간접적으로 접근할 수 있는 가져오기(import) 바인딩을 제공한다.
- object Environent Record
- binding object라는 객체 프로퍼티들을 식별자로 바인딩한다.
- global Environment Record
- 최상위 스코프에 선언된 식별자들과 전역 객체를 바인딩한다.
- declarative ER + objectER 형태로 object ER은 binding object를 통해 내장 전역 객체와 var 키워드로 선언된 변수 등을 참조 가능하며 이것이 window로 접근하는 전역 객체이다. 그 외 나머지 식별자들은 declarative ER에 저장하며 이는 전역 변수라 부른다.
[Lexical Environment와 Variable Environment]
var 키워드로 선언된 변수의 바인딩은
VE
를 통해 찾고, 이외의 식별자들은 LE
를 통해 찾는다.[실행 컨텍스트의 생성 과정]
function foo() { let x = 1; function bar() { const y = 2; var z = 3; console.log(x + y + z); // 6 } bar(); } foo();
- 전역 컨텍스트 생성과 바인딩
- 가장 먼저 전역 컨텍스트가 스택 메모리에 추가되며 Global ER이 생성됨.
- Global ER은 this와 outerEnv필드만 설정되고 이후 foo함수 선언문을 바인딩한다.

- foo 컨텍스트 생성과 바인딩
- foo 함수를 호출하여 새로운 foo 실행 컨텍스트가 되어 제어권을 가져간다.
- foo 실행 컨텍스트도 마찬가지로 LE와 VE로 구성이 되고 OuterEnv로 상위 렉시컬 스코프가 Global ER이므로 이로 정해진다.
- 이후 식별자들과 this가 순차적으로 바인딩 된다.(소스 평가 과정)

- bar 컨텍스트 생성과 바인딩
- bar 컨텍스트도 호출과 함께 생성된다.
- const 로 선언한 변수는 LE에 var로 선언한 변수는 VE에 바인딩 된다.

스코프
스코프는 변수나 매개변수에 접근할 수 있는 범위를 결정한다.
[var 키워드]
ES5까지 변수를 선언할 수 있는 유일한 방법이었다.
var
로 선언된 변수는 기존에 선언된 변수의 값을 덮어쓰며, 함수 스코프를 기준으로 동작한다.특징
- 함수 레벨 스코프 : 함수의 코드 블록만을 스코프로 인정한다. 이는 전역 변수를 남발할 가능성이 높다.
- 변수 호이스팅: 변수를 선언하기 이전에 참조할 수 있다.
이러한 var키워드의 특징은 전역 변수로 인해 문제가 자주 발생하였다. 전역 변수는 스코프를 파악하기 힘들었고 이런 단점을 보완하기 위해 let과 const가 도입되었다.
[let과 const 키워드]
var와 달리 재선언을 허용하지 않으며, 블록 스코프를 가진다.
[함수 스코프와 블록 스코프]
함수 스코프는 선언된 함수 단위로 생성되는 스코프이다.
블록 스코프는 변수의 유효 범위를 블록 단위로 제한하여 사용할 수 있다.
[렉시컬 스코프]
렉시컬 스코프는 변수나 함수를 어디에 작성하였는가에 기초하여 결정된다.
스코프는 함수를 어디에 작성했는가에 따라 명확한 경계를 가지며, 동일한 경계를 가진 스코프는 존재할 수 없다. 즉, 렉시컬 스코프 규칙에 따라 스코프의 경계가 결정되는 것이다.
function foo() { var a = 1; function bar(b) { console.log(a, b); } bar(2); } foo();
- console.log() 메서드에서 참조된 변수 a를 찾기 위해 bar() 함수의 스코프부터 검색을 시작한다.
- bar() 함수의 스코프에는 변수 a를 찾을 수 없으므로 가장 가까운 상위 스코프 foo() 함수 스코프로 올라가 검색한다.
- foo() 함수 스코프에서 변수 a를 찾아 사용하며, 검색은 여기서 중단된다.
중첩된 스코프 내에서 코드가 실행된 경우, 가장 안쪽의 스코프부터 시작하여 상위 스코프로 올라가며 원하는 대상을 검색한다. 이러한 스코프들의 연결 관계를 스코프 체인이라고 스코프 체인을 따라 검색하는 과정을 스코프 체이닝이라고 한다.
함수 스코프와 블록 스코프는 스코프의 단위이고 렉시컬 스코프는 이 스코프들의 범위를 결정하는 규칙이다.
호이스팅
호이스팅은 선언문이 스코프 내의 가장 최상단으로 끌어올려지는 것을 의미한다.
[변수 생성 과정]
- 선언 : 스코프에 변수를 선언한다.
- 초기화 : 변수의 값을 undefined로 초기화하며, 실제로 변수에 접근 가능한 단계이다.
- 할당 : 할당문을 만나면 변수에 실제 값을 할당한다.
[var과 let, const에서의 변수 생성 과정]
var - 선언과 초기화 단계를 한 번에 실행하기 때문에 선언 전에 변수가 접근하여도 이미 초기화가 되어 접근이 가능하다.
let과 const
- 선언 단계는 스코프의 최상단으로 끌어올려져 실행되지만, 초기화 단계는 선언문을 만나면 실행된다.
- 초기화 이전에 변수에 접근하려고 하면 ReferenceError가 발생한다.
- 선언 단계가 실행되는 스코프의 최상단부터 초기화 단계를 실행하는 선언문이 나오기 전까지는 변수에 접근할 수 없다. 이 구간을 Temporal Dead Zone(TDZ)라 부른다.
[함수 선언문의 호이스팅]
함수 선언문의 호이스팅은 함수 선언, 초기화, 할당 세 가지 단계가 모두 동시에 스코프 최상단에서 실행된다. 그렇기 때문에 어느 위치에서든 함수를 호출할 수 있다.
창민 실행컨텍스트
실행 컨텍스트는 어떤 정보가 담겨 있는가?
답변
렉시컬 환경이 담겨져 있다
렉시컬 환경은 환경 레코드(Environment Record)와 외부 렉시컬 환경에 대한 참조(Outer lexical Environment Reference)로 구성되어 있다
환경 레코드는 식별자를 등록하고 식별자에 바인딩된 값을 관리하는 저장소다
외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킨다
호이스팅 (Hoisting)란 무엇인가요?
답변
선언문이 코드의 선두로 올려진 것 처럼 동작하는 특징이 있다
scope란 무엇이며 var, let, const에 대해 설명해주세요
답변
스코프는 식별자가 유효한 범위를 말한다
var 키워드로 선언된 변수는 함수레벨 스코프를 따르며 런타임 이전에 선언단계와 초기화단계가 동시에 일어나 선언문이전에 참조가 가능하다
let, const 키워드로 선언된 변수는 블록레벨 스코프를 따르면 런타임 이전에 선언단계만 실행이 되어 선언문이전에 참조가 불가능하다
스코프 체인은 무엇인가?
답변
스코프가 중첩되어 계층적으로 연결된 것을 스코프 체인이라고 한다