자바스크립트 클로져 ( Closure )
What is Closure ?
외부함수의 맥락(context) , 변수에 접근할 수 있는 내부함수 이며 scope chain으로 표현되기도 합니다.
보통 함수를 return 하여 사용하고 return 하는 내부함수를 closure 함수라고 부릅니다.
또한 함수 선언 시 생성되는 유효 범위를 의미하기도 합니다.
Closure가 가지는 세 가지 scope chain
- Closure 자신에 대한 접근. (Closure function 내에 정의된 변수)
- 외부함수의 변수에 대한 접근
- 전역 변수에 대한 접근
Why use Closure ?
Closure 는 어떤 데이터(어휘적 환경)와 그 데이터를 조작하는 함수를 연결하는 데 있어서 유용합니다.
( 객체지향 프로그래밍의 정보 은닉과 모듈화 같은 이점 들을 얻을 수 있습니다. )
자바와 같은 몇몇 언어들은 Method 를 프라이빗으로 선언할 수 있는 기능을 제공합니다.
자바스크립트는 이런 방법을 제공하지 않지만 Closure 를 통해 프라이빗 Method 를 흉내낼 수 있습니다.
( 프라이빗 Method 는 코드에 제한적인 접근만 허용한다는 점 뿐만 아니라 전역 네임 스페이스를 관리하는
강력한 방법을 제공하여 불필요한 Method 가 공용 인터페이스를 혼란스럽게 만들지 않도록 합니다. )
아래 코드는 프라이빗 함수와 변수에 접근하는 퍼블릭 함수를 정의하기 위해 Closure 를 사용하는 방법입니다.
이렇게 Closure 를 사용하는 것을 모듈 패턴이라 합니다.
Closure example
이제 간단한 Closure 함수의 예시와 활용 예시를 살펴보겠습니다.
function outer(){
console.log("outer");
function inner(){
console.log("inner")
}
return inner;
}
outer() // outer;
outer()() // outer;
// inner;
var what = outer();
what() // inner;
outer 라는 외부함수 내부에 inner 라는 내부함수가 존재합니다.
이 때 Closure 의 외부함수의 변수는 내부함수에 의해 변경될 수 있습니다.
아래 예시를 살펴보겠습니다.
function outerChange() {
var newId = '새로운 아이디';
return {
getId : function() {
return newId;
},
changeId : function(id) {
//내부함수가 외부함수의 변수값을 변경하게 함.
newId = id;
}
}
}
var change = outerChange();
change.getId()// '새로운 아이디'
change.changeId('변경된 아이디')
change.getId()// '변경된 아이디' => 변경된 값을 리턴함.
위처럼 outerChange 의 변수 newId 의 값을 내부함수를 통해 변경할 수 있습니다.
또한 Closure 를 이용해 변수를 scope 안 쪽에 숨겨서 함수 밖으로 노출시키지 않을 수도 있습니다.
function Counter() {
// 카운트를 유지하기 위한 자유 변수
var counter = 0;
// 클로저
this.increase = function () {
return ++counter;
};
// 클로저
this.decrease = function () {
return --counter;
};
}
const counter = new Counter();
console.log(counter.increase()); // 1
console.log(counter.decrease()); // 0
Tip* ( Closure 도 남발하면 좋지 않은 상황이 발생할 수 있습니다. )
가비지 컬렉션 대상이 되어야 할 객체가 메모리 상에 남아 있게 되므로,
Closure 를 남발하면 overflow 가 발생할 수도 있기 때문입니다.