closure
클로저는 자바스크립트와 같은 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다.
MDN에서는 클로저에 대해 이렇게 정의하고 있다.
'클로저는 함수와 함수가 선언된 어휘적 환경(lexical environment)의 조합이다.'
즉, 클로저는 자신이 생성될 때의 환경(Lexical environment)을 기억하는 함수라고 할 수 있다.
lexical scope에 대한 설명은 다음 글에 간단히 설명되어 있다.
2021/01/21 - [분류 전체보기] - Scope(유효 범위)
closure의 활용 예
변수의 값은 누군가에 의해 언제든지 변경될 수 있어 오류 발생의 근본적 원인이 될 수 있다.
함수형 프로그래밍에서 부수 효과(Side effect)를 최대한 억제하여 오류를 피하고 프로그램의 안정성을 높이기 위해 클로저는 적극적으로 사용된다.
closure를 활용함으로써 얻을 수 있는 기능
- 현재 상태를 기억하고 변경된 최신 상태를 유지
- 전역 변수(global scope)의 사용 억제
- 정보의 은닉
var increase = (function () { //즉시실행되는 외부함수
var counter = 0;
return function () { //변수 increase에 할당되는 내부함수
return ++counter; //변수 increase에 할당되는 내부함수의 반환값. 외부함수의 counter변수를 참조하고 있다.
};
}());
for (var i = 0; i < 5; i++){
console.log(increase());
}
//1
//2
//3
//4
//5
위 코드에서 increase변수는 즉시 실행 함수를 통해 ++counter를 반환하는 함수를 값으로 할당받는다.
increase = function () {return ++counter;}
그 후 for문을 통해 반복적으로 increase변수에 할당된 내부 함수를 실행시키면, 외부 함수는 즉시 실행 후 return을 통해 종료되었음에도 불구하고, 내부 함수에서 외부 함수에서 선언된 변수 counter에 지속적으로 접근하여 1, 2, 3, 4, 5의 결과를 얻을 수 있다.
외부 함수는 즉시 실행 함수이기 때문에 counter가 다시 초기화될 일이 없고, 함수 바깥에서 직접 접근할 수 없는 private변수의 역할을 수행하기 때문에 전역 변수(global scope)를 사용할 경우의 의도되지 않은 변경을 걱정할 필요가 없다.
위 코드에서처럼 외부 함수에 정의된 counter와 같은 변수를 자유 변수라고 한다.
closure 사용 시 자주 발생하는 실수
closure 사용 시 자주 발생하는 실수의 대표적인 예이다
var arr = [];
for (var i = 0; i < 5; i++) {
arr[i] = function () {
return i;
};
}
for (var j = 0; j < arr.length; j++) {
console.log(arr[j]());
}
위 코드에 대한 결과로 0, 1, 2, 3, 4를 기대할 것이다.
하지만 for문에서 사용된 변수 i가 전역 변수(global scope)이기 때문에 반환 값이 실시간으로 변경되게 된다.
그러므로 결과는 5, 5, 5, 5, 5로 나타나게 된다.
closure를 사용하여 바르게 동작하는 코드로 수정
var arr = [];
for (var i = 0; i < 5; i++){
arr[i] = (function (id) { //매개변수 id를 가지고 인자로 i를 전달받은 즉시실행 함수 (외부함수)
return function () { //매개변수 id를 반환하는 함수 (내부함수)
return id;
};
}(i));
}
for (var j = 0; j < arr.length; j++) {
console.log(arr[j]());
}
arr [i]의 값으로,
전달받은 매개변수 id를 return 하는 함수 (내부 함수)
를 return 하는즉시 실행 함수(인자로 i를 전달받은)(외부 함수)
를 할당한다.
*for문 안에서 사용된 var는 전역 범위(global scope)를 가지기 때문에 나타나는 문제이다.
block-level scope를 가지는 let을 사용하면 간단히 해결된다.
2021/01/21 - [개발/Javascript] - var, let, const
참고
'개발 > Javascript' 카테고리의 다른 글
객체(object) (0) | 2021.01.28 |
---|---|
arguments, rest parameter (0) | 2021.01.28 |
reduce (0) | 2021.01.24 |
var, let, const (0) | 2021.01.21 |
Scope(유효범위) (0) | 2021.01.21 |