클로저는 자바스크립트의 강력한 기능이지만, 너무 남발하여 사용하면 안 된다. 여기서는 클로저에서 사용자가 쉽게 간과할 수 있는 사항을 정리했다.
클로저의 프로퍼티값이 쓰기 가능하므로 그 값이 여러 번 호출로 항상 변할 수 있음에 유의해야 한다.
function outerFunc(argNum){
var num = argNum;
return function(x) {
num += x;
console.log('num: ' + num);
}
}
var exam = outerFunc(40);
exam(5);
exam(-10);
위 코드에서 보는 바와 같이 exam 값을 호출할 때마다, 자유 변수 num의 값은 계속해서 변화하니 주의해야 한다.
function func() {
var x = 1;
return {
func1 : function() { console.log(++x); },
func2 : function() { console.log(-x); }
};
};
var exam = func();
exam.func1();
exam.func2();
위 코드에서는 반환되는 객체에는 두 개의 함수가 정의되어 있는데, 두 함수 모두 자유 변수 x를 참조한다.
그리고 각각의 함수가 호출될 때마다 x 값이 변화하므로 유의해야 한다.
루프 안에서 클로저 활용할 때는 주의하자.
function countSeconds(howMany) {
for (var i = 1; i<=howMany; i++) {
setTimeout(function() {
console.log(i);
}, i*1000);
}
};
countSeconds(3);
위 코드는 1, 2, 3을 1초 간격으로 출력하는 의도로 만든 예제이다. 하지만 결과는 4가 연속 3번 1초 간격으로 출력된다. 클로저를 잘 이해했다면 이유를 쉽게 이해할 수 있을 것이다.
setTimeout 함수의 인자로 들어가는 함수는 자유 변수 i를 참조한다. 하지만 이 함수가 실행되는 시점은 countSeconds() 함수의 실행이 종료된 이후이고, i 값은 이미 4가 된 상태이다. 그러므로 setTimeout()로 실행되는 함수는 모두 4를 출력하게 된다.
이제 원하는 결과를 얻기 위해 이 코드를 수정해보자. 이를 위해서는 루프 i값 복사본을 함수에 넘겨준다. 이를 위해 즉시 실행 함수를 사용했다.
function countSeconds(howMany) {
for (var i = 1; i<=howMany; i++) {
(function (currentI) {
setTimeout(function() {
console.log(currentI);
}, currentI * 1000);
}(i));
}
};
countSeconds(3);
즉시 실행 함수를 시켜 루프 i 값을 currentI에 복사해서 setTimeout()에 들어갈 함수에서 사용하면, 원하는 결과를 얻을 수 있다.
'Study > JavaScript' 카테고리의 다른 글
[JavaScript] GSAP | TweenMax 쉽게 애니메이션을 구현하는 방법 (0) | 2021.07.18 |
---|---|
[JAVASCRIPT] Call By Value && Call By Reference에 대해서 알아보자 (0) | 2021.04.08 |
[JAVASCRIPT] 변수 선언 var,let,const의 차이점을 알아보자. (0) | 2021.03.30 |
[클로저] 함수의 캡슐화 (0) | 2019.06.16 |
[클로저] 클로저의 개념 (0) | 2019.06.15 |