외부 함수의 변수에 접근할 수 있는 내부 함수 또는 이러한 작동 원리를 일컫는다.
함수와 함수가 선언된 어휘적 환경의 조합
ex)
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
return innerFn;
}
let globalVar = 'global';
let innerFn = outerFn();
innerFn();
라고 하면 클로저함수는 노란색이다.
클로저 함수 안에서는 지역 변수(innerVar), 외부 함수의 변수(outerVar), 전역 변수(globalVar)의 접근이 전부 가능하다.
(문제1) 다음 코드에서 inner 함수에서 접근할 수 있는 Scope는 총 몇개인가?
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
}
let globalVar = 'global';
outerFn();
답은 총 3개이다.
1 .
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
2 .
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
}
3 .
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
}
let globalVar = 'global';
outerFn();
scope는 여기서부터 시작한다.
(문제2)
만약
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
return innerFn;
}
outerFn();
처럼 return innerFn;
이 추가된다면 outerFn()
실행결과는 어떻게 되는가??
이 경우 함수도 리턴할 수 있다.
그럼 다음 문제도 풀어보자.
(문제3)
function outerFn() {
let outerVar = 'outer';
console.log(outerVar);
function innerFn() {
let innerVar = 'inner';
console.log(innerVar);
}
return innerFn;
}
라고 했을 때 다음의 경우 각각 콘솔에 어떻게 찍힐까?
outerFn()(); // ①
let innerFn = outerFn(); // ②
innerFn(); // ③
function adder(x) {
return function(y) {
return x + y;
}
}
이라고 하면
adder(2)(3); // 5 : 2 + 3
let add100 = adder(100); 이라고하면
add100(2); // 102 : 100 + 2
add100(10); // 110 : 100 + 10
let add5 = adder(5); 라고 하면
add5(2); // 7 : 5 + 2
x의 값을 고정해놓고 재사용할 수 있다!
function htmlMaker(tag) {
let startTag = '<' + tag + '>';
let endTag = '</' + tag + '>';
return function(content) {
return startTag + content + endTag;
}
}
let divMaker = htmlMaker('div');
divMaker('code'); // <div>code</div>
divMaker('states'); // <div>states</div>
let h1Maker = htmlMaker('h1');
h1Maker('Headline'); // <h1>Headline</h1>
function makeCounter() {
let privateCounter = 0;
return {
increment: function() {
privateCounter++;
},
decrement: function() {
privateCounter--;
},
getValue: function() {
return privateCounter;
}
}
}
이라고 하면,
let counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue();
let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue();
일 경우 counter1.getValue();
와 counter2.getValue();
의 값은 무엇인가?
답은
let counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue(); // 2
let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue(); // 1
이다.
위의 답처럼 두 카운터에 각기 다른 privateCounter를 다루면서, privateCounter를 밖으로 노출시키지 않는다.