클로저
- 앞서 렉시컬 스코프와 클로저는 매우 밀접하게 연관되어 있다고 말했다. 클로저란 무엇일까?
- 클로저 : 함수와 함수가 선언된 렉시컬 환경(Lexical Environment)을 기억하여 외부 함수가 종료된 후에도 내부 함수가 외부 변수에 접근할 수 있도록 하는 기능이다.
여기서 렉시컬 환경은 또 무엇일까?
렉시컬 환경
- 렉시컬 환경은 "자바스크립트 엔진이 변수와 함수 선언을 관리하기 위해 사용하는 구체적인 공간"을 말한다.
- 렉시컬 스코프는 "함수의 정의 위치를 기준으로 스코프가 결정되는 규칙"을 의미하는 것으로 렉시컬 환경과는 다른 의미를 가진다.
- 예시:
function makeAdder(x) {
return function(y) {
return x + y;
}
}
const add3 = makeAdder(3);
console.log(add3(2)); // 5
- makeAdder(3)이 호출되면, 반환된 내부 함수는 x의 값 3을 렉시컬 스코프를 통해 기억한다.
- add3 변수는 makeAdder(3) 호출의 반환 값인 함수(내부 함수)를 참조한다.
- 최종적으로 add3(2)를 호출하면 내부 함수가 실행되면 y는 2로 전달된다.
function makeAdder(x) {
return function(y) {
return x + y;
}
}
const add3 = function(y) {
return 3 + y;
}
console.log(function(2) {
return 3 + 2;
});
- 위 코드를 렉시컬 환경으로 나타내면 아래와 같다.
다시 돌아와, 클로저의 예시를 살펴보자:
function outer() {
const x = 'outer scope';
function inner() {
return x; // inner는 x를 기억한다.
}
return inner;
}
const myInner = outer();
console.log(myInner()); // "outer scope"
- 위 코드에서 outer 함수가 종료된 후에도, inner 함수는 x를 참조할 수 있다.
- 이는 inner 함수가 렉시컬 스코프를 기반으로 작성되었기 때문에, outer 함수의 스코프 체인을 기억하기 때문이다.
클로저를 통해 은닉화도 가능하다.
function makeCounter() {
let num = 0; //은닉화
return function() {
return num++;
};
}
let counter = makeCounter();
console.log(counter());
console.log(counter());
console.log(counter());
- makeCounter 호출
- makeCounter가 실행되며, num에 0이 저장된다.
- 반환된 내부 함수는 num을 포함한 클로저를 형성한다.
- counter 함수 호출
- 내부 함수가 실행되며, 클로저를 통해 num에 접근한다.
- num 값이 반환된 후 증가한다.
- 데이터 은닉화
- num은 외부에서 직접 접근할 수 없고, 오직 counter 함수 호출을 통해서만 접근할 수 있다.
실행 컨텍스트
- 실행 컨텍스트는 현재 실행중인 코드에 대한 세부 정보(제어 흐름의 위치, 선언된 변수와 함수, this, arguments 등) 를 담고있는 데이터 구조이다.
- 실행 컨택스트의 종류는 아래와 같이 두 가지가 있다.
- 1. Global Execution Context - 스크립트가 처음 실행될때 생성된다.
- 2. Function Execution Context - 함수가 호출될때 생성된다.
이렇게 생성된 Global Execution Context 와 Function Execution Context는 실행 컨택스트 스택 이라는 자료구조에
저장 되고 관리된다.
이 스택은 호출스택(call stack) 이라고도 부르고, '스택' 이므로 후입선출 방식으로 컨택스트를 push / pop 한다.
동작방식
- Global Execution Context
- 스크립트 실행 시 가장 처음 생성되며, 항상 스택의 가장 아래에 위치한다.
- 이후 함수가 호출되면 해당 함수의 실행 컨텍스트가 만들어진다.
- Function Execution Context
- 함수가 호출될 때마다 실행 컨텍스트가 생성되어 스택에 push된다.
- 함수 실행이 종료되면 스택에서 pop되어 제거된다
예시:
<script>
// 스크립트 실행 -> Global Execution Context 가 생성되고 스택에 push된다.
function A(){
B(); // 함수B 의 실행 컨택스트가 생성되고 스택에 push.
}
function B(){
console.log('done!');
}
A(); // 함수A 의 실행 컨택스트가 생성되고 스택에 push.
</script>
그래서 실행 컨텍스트와 렉시컬 환경의 관계는 어떻게 될까?
실행 컨텍스트는 렉시컬 환경을 포함하며, 실행 중인 코드의 실행 정보를 관리한다.
실행 컨텍스트는 자바스크립트 코드 실행의 핵심 도구이며, 실제로 실행 흐름을 제어하는 "실행 도구"로 볼 수 있다.
렉시컬 환경에 저장된 변수/함수, this, 제어 흐름 위치를 포함해 코드 실행에 필요한 모든 정보를 담고 있고 스택 자료구조(Call Stack)를 기반으로 컨텍스트를 생성, 실행, 제거하며, 코드 실행 순서를 제어한다.
따라서 실행 컨텍스트는 렉시컬 환경을 활용하여 변수와 스코프를 관리하고, 스택 자료구조를 통해 실행 흐름을 제어하는 도구로 이해할 수 있다.
'WEB > JavaScript' 카테고리의 다른 글
[JavaScript] 호이스팅, 스코프 (0) | 2025.01.05 |
---|---|
[JavaScript] 변수 선언, 함수 정의 및 형태 (0) | 2025.01.05 |
[JavaScript] 객체 메소드(Object methods) (1) | 2024.01.09 |
[JavaScript] 기능 모듈화 시키기 (0) | 2023.10.16 |
[JavaScript] 화살표 함수, Arrow Function (0) | 2023.10.13 |