let add = function(x) {
let sum = function(y) {
return x + y;
}
return sum;
}
let foo = add(1);
foo(3);
let total = foo(6);
add는 x를 매개변수로 하며 함수 sum을 반환한다.
add는 매개변수 x 를 통해 그 값을 내부함수 sum에게 전달해준다
이때 sum은 외부함수인 add의 변수 x에 접근할 수 있으므로 클로저이다.
total의 값인 foo(6) 은 add(1)(6) 과 같고 답은 7이다.
그렇다면 foo(3)은?
👉🏻 실행되면 4가 되지만 어떤 변수에도 할당되지 않았기에 total에 영향을 미치지 않는다.
var a = 0;
function foo() {
var b = 0;
return function() {
console.log(++a, ++b);
};
}
var f1 = foo();
var f2 = foo();
f1(); // --> A
f1(); // --> B
f2(); // --> C
f2(); // --> D
여기서 변수 a 는 글로벌 변수 / 변수 b 는 로컬 변수로 볼 수 있습니다.
변수 b 는 함수 안에 선언되어 있기 때문에(= local 변수) f1()을 실행할 때, f2()를 실행할 때 각각 카운트가 올라가는 것이고,
변수 a 는 함수 밖에 선언되어 있기 때문에(= global 변수) f1(), f2() 중 어떤 것을 실행해도 카운트가 올라갑니다.
f1(); 1 1
f1(); 2 2
f2(); 3 1
f2(); 4 2
(Advanced Challenge) 클로저가 가장 유용하게 사용되는 상황은 현재 상태를 기억하고 변경된 최신 상태를 유지하는 것입니다.
다음은 클로저가 유용하게 사용되는 상황인 버튼을 클릭하면 나타나고 사라지는 토글을 구현한 예제 코드입니다. 클로저 개념을 활용해서 isShow 변수의 Javascript 를 작성해 보세요.
<!DOCTYPE html>
<html>
<body>
<button class="toggle">toggle</button>
<div class="box" style="width: 100px; height: 100px; background: red;"></div>
<script>
var box = document.querySelector('.box');
var toggleBtn = document.querySelector('.toggle');
var toggle = (function () {
var isShow = false;
// TODO: ① 클로저를 반환하는 함수를 작성하세요.
return function () {
// TODO: ③ isShow 변수의 상태를 변경하는 코드를 작성하세요.
};
})();
// ② 이벤트 프로퍼티에 클로저를 할당
toggleBtn.onclick = toggle;
</script>
</body>
</html>
① 작성한 함수는 자신이 생성됐을 때의 렉시컬 환경(Lexical environment)에 속한 변수 isShow를 기억하는 클로저입니다. 변수 isShow는 box 요소의 표시 상태를 boolean 값으로 나타냅니다.
② 버튼을 클릭하면 이벤트 프로퍼티에 할당한 이벤트 핸들러인 클로저가 호출됩니다. 함수가 호출될 때 상황에 따라 변수 isShow의 값이 변경됩니다. 변수 isShow는 클로저에 의해 참조되고 있기 때문에 유효하며 자신의 변경된 최신 상태를 계속해서 유지할 수 있습니다.
var box = document.querySelector('.box');
var toggleBtn = document.querySelector('.toggle');
var toggle = (function () {
var isShow = false;
// TODO: ① 클로저를 반환하는 함수를 작성하세요.
return function () { box.style.display = isShow ? 'block' : 'none';
isShow = !isShow;// TODO: ③ isShow 변수의 상태를 변경하는 코드를 작성하세요.
};
})();
// ② 이벤트 프로퍼티에 클로저를 할당
toggleBtn.onclick = toggle;