클로저
클로저는 자바스크립트 고유의 개념은 아니고, 여러 함수형 프로그래밍 언어에서 보편적으로 나타나는 특성이다.
- 함수 선언시 만들어지는 유효 범위가 사라진 후에도 그것을 호출할 수 있는 함수
- 생명주기 상 끝난 외부함수의 변수를 참조하는 함수
어떤 함수 내부에서 선언된 함수 호출 시 활성화되는 실행 컨텍스트의 L.E (Lexical Environment) 객체는
┌ environment Record : 식별자 수집 -> 호이스팅
└ outer Environment Reference : 스코프 체인
으로 이루어지는데 그 중 outer Environment Reference 가 함수가 선언되는 환경, 즉 외부 함수를 참조한다.
function A(){
var a = 10;
function B (){
var b = 10;
console.log(++a);
}
B();
}
A();
함수 A 에서는 변수 b에 접근할 수 없다.
함수 B 에서는 A 내부에서 선언된 변수 a 에 접근할 수 있다.
왜냐하면 B 내부 environment Record 에서는 a 값을 찾지 못하기때문에 상위 컨텍스트인 outer Environment Reference 에 접근하는데, A의 L.E 를 참조하기 때문이다
A 실행 컨텍스트가 종료되면 더이상 a, function B 를 참조하는 대상이 없기 때문에 (참조 카운트 = 0) GC(가비지 컬렉터)의 수거 대상이 된다.
function A(){
var a = 10;
function B (){
var b = 10;
return ++a;
}
return B;
}
var A2 = A();
console.log(A2()); // 2
console.log(A2()); // 3
A 함수 내부에서 B를 실행하거나, B의 실행값 B() 를 리턴하는것이 아니라 B함수 자체를 리턴하면
A 함수의 실행 컨텍스트가 종료되더라도 A2 변수가 A함수의 실행 결과인 B 함수를 리턴하게 된다.
→ B함수가 A함수의 LE를 참조하므로 가비지 컬렉터의 수집 대상에서 제외된다. 따라서 a에 접근할 수 있음
a를 참조하는 내부함수 B를 외부로 전달할 때 A 함수의 실행 컨텍스트가 사라져도 변수 a가 사라지지 않는다
- 외부로 전달하는 방법 : return, 또는 콜백함수 (setTimeout, setInterval, addEventListener 등의 인자로 전달되는)
메모리 소모는 클로저의 기본 특성이기 때문에
→ 더이상 사용하지 않는다면 참조 카운트를 0으로 만들어야 한다. (메모리 누수 방지)
참조하고 있는 식별자에 null 이나 undefined 를 할당한다
var outer = (function() {
var a = 1;
var inner = function() {
return ++a;
}
return inner
}
outer2 = outer()
console.log(outer2())
console.log(outer2())
outer2 = null //outer() =inner func에 대한 Reference를 해제시켜서 메모리 누수 방지
▼setInterval에 의한 클로저의 메모리 해제
let counter = 0;
const intervalId = setInterval(() => {
counter++;
console.log(counter);
if (counter === 5) {
clearInterval(intervalId);
console.log('Interval cleared');
// 클로저가 `counter`를 계속 참조하고 있는 것을 방지하기 위해 `counter`를 null로 설정
counter = null;
}
}, 1000);
▼ eventListener에 의한 클로저의 메모리 해제
const button = document.querySelector('button');
let clickCount = 0;
// 이벤트 핸들러 함수
function handleClick() {
clickCount++;
console.log(`Button clicked ${clickCount} times`);
if (clickCount === 5) {
console.log('Removing event handler after 5 clicks');
// 핸들러를 null로 설정하여 참조 끊기
button.removeEventListener('click', handleClick);
handleClick = null; // 핸들러 자체를 null로 설정하여 더 이상 참조되지 않도록 함
}
}
// 이벤트 리스너 등록
button.addEventListener('click', handleClick);
'개발 공부 일지 > 코어 자바스크립트 (정재남)' 카테고리의 다른 글
[코어 자바스크립트] 프로토타입 (0) | 2025.03.10 |
---|---|
[코어 자바스크립트] 클로저 활용 사례 (0) | 2025.03.04 |
[코어 자바스크립트] 비동기 제어로 콜백 지옥 탈출하기 (1) | 2025.02.25 |
[코어 자바스크립트] 콜백 함수 (0) | 2025.02.25 |
[코어 자바스크립트] this - 명시적 바인딩 (0) | 2025.02.21 |