Execution Context(실행 컨텍스트)란 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
자바스크립트는 동일한 환경에 있는 환경 정보들을 모은 실행 컨텍스트를 콜스택에 쌓아 올린 후 실행하며 코드의 환경과 순서를 보장스택은 LIFO(Last In, First Out)의 구조로 마지막에 들어온 정보를 가장 먼저 접근한다.한다.
여기서 환경이란 전역공간 또는 함수 내부의 환경이 될 수 있다.
✅ 예제
var temp = 'temp';
function b (){
console.log('안녕하세용');
}
function a (){
b();
}
a();
(1) 콜스택에는 전역 컨텍스트말고 다른 컨텍스트는 없기 떄문에 전역 컨텍스트와 관련된 코드를 진행한다.
(2) 전역 컨텍스트와 관련된 코드를 진행 중 a함수를 실행하였기에 a함수의 환경 정보들을 수집하여 a 실행 컨텍스트를 생성하고 콜스택에 담는다. 콜스택 최상단에 a 실행 컨텍스트가 있기에 기존의 전역 컨텍스트와 관련된 코드의 실행을 일시적으로 중단한 후 a 실행 컨텍스트의 코드를 실행한다.
(3) a 함수 내부에서 b 함수를 실행하였기에 b 함수의 환경 정보들을 수집, 실행 컨텍스트를 생성, 콜스택에 담는다. 이전과 똑같이 콜스택 최상단에 b 실행 컨텍스트가 있기에 기존 a 실행 컨텍스트와 관련된 코드의 실행을 일시적 중단한다.
(4) b 함수가 종료된 후 b 실행 컨텍스트가 콜스택에서 제거된다. 제거 후 콜스택 최상단에는 a 실행 컨텍스트가 있기에 이전에 중단된 지점부터 코드 진행이 재개된다.
(5) a 함수 또한 종료된 후 실행 컨텍스트가 콜스택에서 제거된다.
(6) 전역 공간에 실행할 코드가 남아있지 않다면 콜스택에서 전역 컨텍스트 또한 제거되며 콜스택에 아무것도 남지 않은 상태로 종료된다.
Execution Context(실행 컨텍스트)가 가지고 있는 정보들
자바스크립트의 Variable Environment, Lexical Environment, This Binding은 실행 컨텍스트(Execution Context)와 깊은 관련이 있다.
1️⃣ Variable Environment (변수 환경) : 변수와 함수 선언을 저장하는 공간을 의미
Lexical Environment의 한 종류로, 실행 컨텍스트가 생성될 때 함께 생성된다.
✅ Variable Environment의 특징
- 실행 컨텍스트가 생성될 때 함꼐 생성된다.
- var로 선언된 변수는 Variable Environment에 저장된다.
- 함수 선언문도 Variable Environment에 저장된다.
✅ 예제
function example() {
var a = 10;
function inner() {
console.log(a);
}
}
// 위 코드에서 Variable Environment에는 다음과 같은 정보가 저장된다.
Variable Environment:
- a: 10
- inner: function
// example 함수가 실행되면, inner는 a를 참조할 수 있다.
2️⃣ Lexical Environment (렉시컬 환경) : 변수, 함수, this 바인딩을 저장하는 공간을 의미
실행 컨텍스트가 생성될 때 Variable Environment와 함께 생성되며, 스코프 체인(Scope Chain)을 형성하는데 중요한 역할을 한다.
✅ Lexical Environment의 구조
- 환경 레코드(Environment Record)
현재 실행 중인 스코프에서 선언된 변수, 함수, this등을 저장하는 객체 - 외부 렉시컬 환경 참조(Outer Lexical Environment Reference)
상위 스코프(부모 스코프)의 Lexical Environment를 참조하는 포인터
✅ Lexical Environment 예제
function outer() {
let a = "Hello";
function inner() {
let b = "World";
console.log(a, b);
}
inner();
}
outer();
// 위 코드의 실행 컨텍스트는 다음과 같이 형성된다.
Global Lexical Environment:
- outer: function
outer Lexical Environment:
- a: "Hello"
- inner: function
- Outer: Global
inner Lexical Environment:
- b: "World"
- Outer: outer Lexical Environment
// inner()가 실행될 때 b는 inner Lexical Environment에서 찾는다.
// a는 outer Lexical Environment에서 찾는다.
✅ Lexical Environment과 var, let, const
var: Variable Environment에 저장된다. 함수 스코프
let, const: Lexical Environment에 저장된다. 블록 스코프
function test() {
if (true) {
var a = 1;
let b = 2;
const c = 3;
}
console.log(a); // ✅ 1 (var는 함수 스코프)
console.log(b); // ❌ ReferenceError (let은 블록 스코프)
console.log(c); // ❌ ReferenceError (const도 블록 스코프)
}
test();
✅ environmentRecord(환경 레코드): 변수와 함수의 식별자(이름과 그 값)를 저장하는 곳
자바스크립트에서 변수를 선언하면, 그 정보가 EnvironmentRecord에 저장된다.
즉, 현재 실행 중인 스코프에서 어떤 변수가 사용 가능한지 기록해 두는 객체라고 보면 된다. 또 자바스크립트의 스코프, 실행 컨텍스트, 클로저 같은 개념을 이해할 때 중요한 역할을 한다.
그리고 실행 컨텍스트 내부 전체를 처음부터 끝까지 확인하여 순서대로 수집한다.
다음 예시를 보면,
var cat = "saebyeok";
console.log(cat); // saebyeok
console.log(cat); // undefined
var cat = "saebyeok"
두번째 예문에서 cat은 선언하기 전에 호출을 먼저 했는데 에러가 발생하지 않고 undefined가 출력이 된다.
이는 호이스팅이라는 현상때문이다.
참고 : https://ssb2046.tistory.com/22
[TIL] 호이스팅(hoisting)이란?
변수와 함수 선언이 해당 범위의 최상위로 끌어올려지는 동작을 말한다. 자바스크립트는 실행 전 한번 훑어보기 때문에 변수와 함수 선언이 먼저 처리되는 것이다.이처럼 끌어올려진 것처럼 동
ssb2046.tistory.com
✅ outerEnvironmentReference
해당 함수가 선언된 위치의 LexicalEnvironment를 참조하고, 변수에 접근했을 때 해당 LexicalEnvironment에서 발견이 되면 사용하고 아니면 다시 outerEnvironmentReference를 참조하여 탐색하는 과정을 반족한다. 이러한 과정을 스코프 체인이라고 한다.
3️⃣ This Binding (this 바인딩): 함수가 실행될 때 this가 어떤 객체를 참조하는 결정하는 과정
함수를 호출하는 방식에 따라 this 값이 달라진다는 점이 중요하다.
✅ this 바인딩이 결정되는 규칙
- 일반 함수 호출: this는 undefined(strict mode) 또는 window/global
- 객체의 메서드 호출: this는 해당 객체를 참조
- 생성자 함수 호출 (new 사용): 새로운 객체를 가리킴
- 화살표 함수: this를 상위 스코프에서 상속받음(Lexical this)
- call, apply, bind를 사용한 호출: this를 명시적으로 지정 가능
✅ 예제: this 바인딩
1️⃣ 일반 함수 호출
function globalFunc() {
console.log(this);
}
globalFunc(); // window (strict mode에서는 undefined)
2️⃣ 객체의 메서드 호출
const obj = {
name: "Alice",
sayHello() {
console.log(this.name);
}
};
obj.sayHello(); // "Alice" (`this`는 `obj`)
3️⃣ 생성자 함수
function Person(name) {
this.name = name;
}
const person = new Person("Bob");
console.log(person.name); // "Bob" (`this`는 새로 생성된 객체)
4️⃣ 화살표 함수 (this 상속)
const obj = {
name: "Charlie",
sayHello: () => {
console.log(this.name);
}
};
obj.sayHello(); // undefined (`this`는 obj가 아니라 상위 스코프를 따름)
🚨이 코드에서 this는 왜 obj가 아닐까?
- sayHello는 화살표 함수이므로 this를 상위 스코프에서 찾음.
- 객체 리터럴(obj) 자체는 실행 컨텍스트를 만들지 않음.
- 따라서, obj가 아니라 obj가 선언된 스코프(즉, 전역 스코프)의 this를 참조함.
- 즉, sayHello() 내부의 this는 obj가 아니라 전역 객체를 가리키게 됨.
📌객체 리터럴 내의 일반 함수와 화살표 함수 비교
const obj = {
name: "Charlie",
sayHello() {
console.log(this.name);
},
sayHelloArrow: () => {
console.log(this.name);
}
};
obj.sayHello(); // "Charlie" (this는 obj를 가리킴)
obj.sayHelloArrow(); // undefined (this는 obj가 아니라 전역 객체)
✅ 위 코드 설명
- 일반 함수(sayHello)
- 객체의 메서드로 호출되었기 때문에 this는 obj를 가리킴
- 즉, sayHello() 내부에서 this.name은 "Charlie"가 됨 - 화살표 함수(sayHelloArrow)
- 화살표 함수는 this를 자신이 선언된 스코프에서 가져옴
- sayHelloArrow가 선언된 스코프는 전역 스코프이므로 this는 window(브라우저) 또는 global(Node.js)를 가리킴
- 전역객체에는 name 프로퍼티가 없으므로 undefined가 출력됨
🔥 한 줄 정리
화살표 함수는 생성자 함수처럼 자체적인 실행 컨텍스트(스코프)를 만들지 않으며, 선언될 당시의 상위 스코프(렉시컬 환경)의 this를 그대로 사용한다.
5️⃣ call, apply, bind (this를 명시적으로 지정할 수 있음)
function greet() {
console.log(this.name);
}
const user = { name: "David" };
greet.call(user); // "David"
greet.apply(user); // "David"
const boundGreet = greet.bind(user);
boundGreet(); // "David"
✨ 정리
Variable Environment | 변수와 함수 선언을 저장하는 공간 (Lexical Environment의 한 부분) |
Lexical Environment | 변수, 함수, this 바인딩을 저장하고, 상위 스코프 참조 (스코프 체인) |
This Binding | 함수가 실행될 때 this가 어떤 객체를 가리키는지 결정 |
👉 핵심 포인트
- Variable Environment는 실행 컨텍스트에서 변수와 함수를 관리.
- Lexical Environment는 스코프 체인을 형성하는 핵심 요소.
- this 바인딩은 호출 방식에 따라 값이 다르게 결정됨.
✨ 총정리
이렇게 실행 컨텍스트는 VariableEnvironment, LexicalEnvironment, EnvironmentRecord, OuterEnvironmentReference, ThisBinding 등 여러 정보들이 합쳐진 것이고, 이러한 정보들이 콜스택에 쌓여 우리가 작성한 코드가 실행되는 것이다.
참고한 블로그 : https://gamguma.dev/post/2022/04/js_execution_context#environmentrecord
'JavaScript' 카테고리의 다른 글
(퀵/병합) 정렬 개념 정리 (0) | 2025.01.08 |
---|---|
힙 개념 정리 (0) | 2025.01.07 |
해시 개념 이해하기 (0) | 2025.01.06 |
[프로그래머스 Lv.1] 문자열 나누기 (0) | 2025.01.04 |
[프로그래머스][스택/큐] 올바른 괄호, 프로세스 javascript (1) | 2024.12.14 |