let seenYet = function() {
let archive = {};
return function(val) {
if(archive[val] {
return true;
}
archive[val] = true;
return false;
}
}
seenYet 함수가 return 하고 있는 익명 함수가 클로저 function 입니다.
seenYet이 반환하는 익명함수는 외부함수 seenYet의 스코프에 선언된 변수 archive에 접근할 수 있기 때문에 클러저입니다.
let add = function(x) {
let sum = function(y) {
return x + y;
}
return sum;
}
let foo = add(1);
foo(3);
let total = foo(6);
함수 add는 매개변수로 하며, 함수 sum을 반환합니다.
add(1)을 통해 x에 넣어주게 됩니다. 이때 x에 1이 저장됩니다.
이후 foo(3)을 통해 3을 y에 넣어줍니다. 따라서 foo(3)은 4를 반환하지만
문제는 total을 구하는 것이고 foo(6)를 통해 1+6 (이때 x에는 계속 1이 저장된 상태입니다.) 7을 반환합니다.
foo(3)은 total에 아무런 영향을 미치지 않습니다.
let multipllyByX = function(x) {
return function(y) {
return x * y;
}
}
let multiplyBy5;
mulltiplyBy5 = multiplyByX(5); // x를 5로 저장하고
multiplyBy5(4); y에 4를 저장해서 사용할 수 있다.
리턴 함수가 x에 접근할 수 있기 때문에 multiplyByX가 클로저를 사용하고 있다고 볼 수 있습니다.
클로저는 "함수와 함수가 선언된 어휘적(lexical) 환경의 조합을 말합니다. 이 환경은 클로저가 생성 된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다." 라고 합니다. 여기서의 키워드는 "함수가 선언"된 "어휘적(lexical) 환경"입니다. 특이하게도 자바스크립트는 함수가 호출되는 환경와 별개로, 기존에 선언되어 있던 환경 - 어휘적 환경 - 을 기준으로 변수를 조회하려고 합니다.
var a = 0;
function foo() {
var b = 0;
return function() {
console.log(++a, ++b);
};
}
var f1 = foo();
var f2 = foo();
f1();
f1();
f2();
f2();
a는 현재 글로벌 변수 입니다. 반대로 b는 로컬 변수입니다.
f1, f2 를 실행해도 a는 계속해서 카운트가 올라갑니다.
하지만 f2를 실행하는 순간 b는 0으로 다시 초기화 됩니다.
따라서
f1(); 을 실행하면 1 1
f1(); 을 또 실행하면 2 1
f2(); 를 실행하면 3 1
f2(); 를 또 실행하면 4 2 와 같은 결과를 얻을 수 있습니다.