내부변수를 사용하는 외부함수를 다른 지역의 변수에 할당함으로써
내부 변수에 접근할 수 있게 한다. - 클로저
var counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
};
})();
console.log(counter.value()); // logs 0
counter.increment();
counter.increment();
console.log(counter.value()); // logs 2
counter.decrement();
console.log(counter.value()); // logs 1
이전 예제에서 각 클로저들이 고유한 문법적 환경을 가졌지만
여기서 우리는 counter.increment, counter.decrement, counter.value
세 함수에 의해 공유되는 하나의 어휘적 환경을 만든다.
공유되는 어휘적 환경은 실행되는 익명 함수 안에서 만들어진다.
이 익명 함수는 정의되는 즉시 실행된다.
이 어휘적 환경은 두 개의 프라이빗 아이템을 포함한다.
하나는 privateCounter라는 변수이고 나머지 하나는 changeBy라는 함수이다.
둘 다 익명 함수 외부에서 접근될 수 없다.
대신에 익명 래퍼에서 반환된 세 개의 퍼블릭 함수를 통해서만 접근되어야만 한다.
위의 세 가지 퍼블릭 함수는 같은 환경을 공유하는 클로저다.
자바스크립트의 어휘적 유효 범위 덕분에 세 함수 각각 privateCounter 변수와
changeBy 함수에 접근할 수 있다.
카운터를 생성하는 익명 함수를 정의하고 그 함수를 즉시 호출하고
결과를 counter 변수에 할당하는 것을 알아차렸을 것이다.
이 함수를 별도의 변수 makeCounter 저장하고
이 변수를 이용해 여러 개의 카운터를 만들 수 있다.
카운터를 생성하는 익명 함수를 정의하고 그 함수를 즉시 호출하고
결과를 counter 변수에 할당하는 것을 알아차렸을 것이다.
이 함수를 별도의 변수 makeCounter 저장하고
이 변수를 이용해 여러 개의 카운터를 만들 수 있다.
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
};
var counter1 = makeCounter();
var counter2 = makeCounter();
alert(counter1.value()); /* 0 */
counter1.increment();
counter1.increment();
alert(counter1.value()); /* 2 */
counter1.decrement();
alert(counter1.value()); /* 1 */
alert(counter2.value()); /* 0 */
두 개의 카운터가 어떻게 다른 카운터와 독립성을 유지하는지 주목해보자.
각 클로저는 그들 고유의 클로저를 통한 privateCounter 변수의 다른 버전을 참조한다.
각 카운터가 호출될 때마다; 하나의 클로저에서 변수 값을 변경해도
다른 클로저의 값에는 영향을 주지 않는다.
// 전역 범위 (global scope)
var e = 10;
function sum(a){
return function(b){
return function(c){
// 외부 함수 범위 (outer functions scope)
return function(d){
// 지역 범위 (local scope)
return a + b + c + d + e;
}
}
}
}
console.log(sum(1)(2)(3)(4)); // log 20 //
// 전역 범위 (global scope)
var e = 10;
function sum(a){
return function(b){
return function(c){
// 외부 함수 범위 (outer functions scope)
return function(d){
// 지역 범위 (local scope)
return a + b + c + d + e;
}
}
}
}
console.log(sum(1)(2)(3)(4)); // log 20
// 익명 함수 없이 작성할 수도 있다.
// 전역 범위 (global scope)
var e = 10;
function sum(a){
return function sum2(b){
return function sum3(c){
// 외부 함수 범위 (outer functions scope)
return function sum4(d){
// 지역 범위 (local scope)
return a + b + c + d + e;
}
}
}
}
var s = sum(1);
var s1 = s(2);
var s2 = s1(3);
var s3 = s2(4);
console.log(s3) //log 20