클로저는 함수와 함수가 선언될 당시의 렉시컬 환경(Lexical Environment)을 함께 기억하는 특별한 구조입니다.
다음 예제를 통해 설명해볼게요:
function greet(name) {
return function() {
console.log("Hello, " + name);
};
}
const greetJohn = greet("John");
greetJohn(); // "Hello, John" 출력
greet("John") 호출:
greet 함수가 호출되면서, 매개변수 name에 "John" 값이 전달됩니다.greet의 실행이 끝난 후에는 정상적으로라면 name 변수가 메모리에서 사라져야 합니다.새로운 함수 반환:
greet 함수 내부에서 생성된 익명 함수는 name 변수에 의존하고 있습니다.name에 접근할 수 있도록 name 변수를 클로저(특별한 기억 공간)에 저장합니다.greetJohn 실행:
greetJohn)를 호출할 때, name 변수는 클로저에 의해 기억되고 사용됩니다."Hello, John"이 정상적으로 출력됩니다.위 코드를 렉시컬 환경 관점에서 살펴보면 다음과 같습니다:
function greet(name) {
// greet 함수 실행 시 렉시컬 환경 생성
// Lexical Environment:
// {
// name: "John"
// }
return function() {
console.log("Hello, " + name); // 클로저를 통해 name 접근
};
}
name 변수를 참조하고 있습니다.name을 메모리에서 지우지 않고 클로저를 통해 유지합니다.greet("John") 호출이 끝난 후에도 반환된 함수는 name 변수("John")에 접근할 수 있습니다.상태 유지:
비공개 데이터 관리:
function counter() {
let count = 0; // 외부 함수의 변수
return function() {
count++; // 외부 변수에 접근
console.log("Count:", count);
};
}
const increment = counter(); // 클로저 생성
increment(); // Count: 1
increment(); // Count: 2
increment(); // Count: 3
counter 함수가 실행될 때, 변수 count가 생성됩니다.counter는 새로운 함수(클로저)를 반환합니다.count 변수에 접근할 수 있습니다.increment()를 호출할 때마다, 클로저를 통해 count 값을 유지하며 증가시킵니다.name이 "John"으로 클로저에 의해 저장된다는 말은, 반환된 함수가 외부 함수의 name 변수에 접근할 수 있도록 메모리에서 변수를 유지한다는 뜻입니다.