클로저란?
함수가 정의될 때 렉시컬환경을 기억하는 함수를 말합니다.
간략히 아래의 예제로 살펴보겠습니다.
소스코드 — example.js
function createCounterClosure() {
let count = 0;
return {
increase: function() {
count++;
},
getCount: function() {
return count;
}
}
}
const counter1 = createCounterClosure();
const counter2 = createCounterClosure();
counter1.increase();
counter1.increase();
console.log('counter 1의 값 : ' + counter1.getCount());
counter2.increase();
console.log('counter 2의 값 : ' + counter2.getCount());
실행 결과
counter 1의 값 : 2
counter 1의 값 : 1
객체지향프로그래밍에서 인스턴스와 비슷한 느낌입니다.
그럼 다른 예제도 보겠습니다.
example.js
for (var i = 0; i < 5; i++) {
setTimeout(function() {
i = 0;
console.log(i);
}, 1000)
}
위의 코드는 0 1 2 3 4를 출력할 것 같지만
5 5 5 5 5를 출력합니다.
이런 결과가 나타난 이유는 클로저는 외부 변수에 대해 값이 아닌 참조로 접근하기 때문입니다.
즉, 클로저는 최종 갱신된 변수(i)에 대해서만 접근할 수 있으므로, 외부 함수가 전체 for문을 실행하고
리턴한 최종 i의 값을 리턴하게 됩니다.
example.js
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(function() {
console.log(j);
}, 1000);
})(i);
}
이런 부작용을 고치기 위해서 “즉시 호출된 함수 표현식(Immediately Invoked Function Expression. IIFE)”를
사용할 수 있습니다. 이러면 i의 값이 j에 대입되어 0 1 2 3 4가 출력됩니다.