scope의 연장으로 생각하면 쉬움.
array method, callback을 배울 때 함수를 파라미터로 받을 수 있는 것을 배웠지만, 여기선 함수를 리턴할 수 있단 것도 알 수 있다.
function outerFn() {
let outerVar = 'outer';
console.log(outerVar); // 이로 인해 콘솔창에 outerVar의 값이 찍히고,
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
return innerFn; // 아직 실행되지 않은 함수(innerFn)가 리턴됨.
}
outerFn(); // 출력 1.outer 2.innerFn(실행되지 않은채로)
outerFn()(); // 출력 1.outer 2.inner (innerFn에 ()가 붙어, innerFn이 실행됨)
let innerFn = outerFn(); //출력 outer; innerFn이 실행되지 않은채로 return.
//이 상태에서 콘솔창에 innerFn 찍으면 innerFn에 대한 설명을 볼 수 있음.
innerFn(); //출력 inner; 위에서 outerFn()돌린 후 innerFn에 ()를 찍으니까.
Closure(클로저)
외부 함수의 변수에 접근할 수 있는 내부 함수.
또는, 이러한 작동 원리를 일컫는 용어.
(위의 innerFn가 클로저 함수.)
- 클로저 함수 안에서는 아래의 접근이 모두 가능함.
- 지역 변수(innerVar)
- 외부 함수의 변수(outerVar)
- 전역 변수(globalVar)
커링
함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법.
- 유용한 이유
- x의 값을 고정해놓고 재사용할 수 있다.
- 외부 함수의 변수가 저장되어 마치 템플릿 함수와 같이 사용 가능(특히 html)
- 참조: 커링에 대해 정리한 글
예제1)
function adder(x) {
return function(y) {
return x + y;
}
}
adder(2)(3); //5
예제2)
let add100 = adder(100);
add100(2); // 102
add100(10); //110
let add5 = adder(5)
add5(2); //7
예제3)
html에서 ~Maker 만들 경우
function htmlMaker(tag) {
let startTag = '<' + tag + '>'
let endTag = '</' + tag + '>'
return function(content) {
return startTag + content + endTag;
}
}
let divMaker = htmlMaker('div')
divMaker('안녕하세요') // "<div>안녕하세요</div>"
let spanMaker = htmlMaker('span')
spanMaker('오오') // "<span>오오</span>"
클로저 모듈 패턴
변수를 스코프 안쪽에 가두어 함수 밖으로 노출시키지 않는 방법.
- 유용한 이유
- x의 값을 고정해놓고 재사용할 수 있다.
- 외부 함수의 변수가 저장되어 마치 템플릿 함수와 같이 사용 가능(특히 html)
function makeCounter() {
let privateCounter = 0;
return{
increment: function() {
privateCounter++;
},
decrement: function() {
privateCounter--;
},
getValue: function() {
return privateCounter;
}
}
}
두 카운터에 각기 다른 privateCounter를 다루면서,
privateCounter를 밖으로 노출시키지 않는다.
let counter 1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue(); //2
>
let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue(); //1