클로저는 자바스크립트의 정말(!!!) 난해한 개념으로, 어렵지만 고급 기술을 위해서는 필수적인 개념이다. MDN에서는 클로저를 다음과 같이 정의하고 있다.
클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.
정의 역시 난해하다. 이를 이해하기 위해선 우선 어휘적 환경, 즉, 렉시컬 환경에 대해 먼저 이해해야 한다.
const test=1;
function outer(){
const test = 10 ;
function inner() {
console.log (test); //10
}
inner()
}
outer()
위의 코드에서 inner함수는 outer함수의 중첩함수로 정의되었고, 호출된다. inner함수의 상위 스코프는 outer()함수의 스코프이다. 따라서 inner함수는 outter함수에서 선언된 변수 test에 접근할 수 있다. 만약 inner함수가 outer함수의 중첩함수가 아니었다면 outer에서 선언된 변수에 접근할 수 없었을 것이다.
const test=1;
function outer(){
const test = 10 ;
}
function inner() {
console.log (test); // 1
}
outer()
자바스크립트는 함수가 어디서 정의되었느냐에 따라 상위 스코프를 결정하는데 이를 렉시컬 스코프라 한다. 그렇기 때문에 inner함수는 자신이 정의되었던 스코프를 기억하고 변수 test를 사용할 수 있는 것이다. 한가지 더 예를 들면
const test = function(x) {
return function(y) {
return x-y //중첩함수가 외부함수의 변수 x에 접근
}
}
이와 같이 "외부 함수의 변수에 접근가능한 중첩함수"를 클로저라고 한다. 클로저의 특징은 함수를 리턴하는 함수라는 점, 그리고 중첩함수가 외부 함수의 변수에 접근 가능하다는 점이다. 또한, 클로저는 리턴하는 함수에 의해 스코프(변수의 접근 범위)가 구분되는데, 따라서 클로저의 핵심은 스코프를 이용해서 변수의 접근 범위를 닫는(closure; 폐쇄) 데에 있다. 때문에 함수를 리턴하는 것만큼이나 변수가 선언된 곳이 중요하다.
const test = function(x) {
return function(y) {
return x-y //중첩함수가 외부함수의 변수 x에 접근
}
}
const fiveMinus = test(5);
fiveMinus(1) // 4
fiveMinus(4) // 1
원래 함수의 실행이 끝나고 나면 함수 내부에 정의된 변수를 사용할 수 없다. 그러나 클로저를 사용하면 보다시피 함수의 실행이 끝나고도 변수를 사용할 수 있다. 클로저는 이처럼 특정 데이터를 함수에 가두어 계속해서 사용할 수 있게 한다.
또한 정보에 접근을 제한해 정보를 보호할 수도 있다. 다음을 보자
const oddMaker = function() {
let value = 0;
return {
increase : () => {
value += 2 } ,
decrease : () => {
value -= 2 } ,
getValue : () => {
value }
}
}
const maker1 = oddMaker();
maker1.increase();
const maker 2 = oddMaker();
maker2.increase();
단 하나의 함수를 리턴하는것이 아니라 객체를 이용해 여러개의 함수를 리턴할 수 있도록 만들었다. oddMaker는 객체를 리턴하므로 maker1은 객체이다. 이 때, maker1을 이용하지 않고서는 oddMaker의 변수 value를 바꿀 방법이 없다. 이것을 바로 정보의 접근 제한, 캡슐화 라고 부른다. 캡슐화의 장점은 의도치 않은 변경, 즉 side effect를 줄일 수 있다는 점이다. 따라서 변경에 따른 오류의 위험을 줄일 수 있다.
또한 oddMaker에 의해 리턴된 객체는 내부의 변수 value값을 각각 독립적으로 가지게 된다. 따라서 maker1과 maker2는 서로 영향을 미치지 않고 독립적이다. 이처럼 함수의 재사용성을 극대화하여 함수를 완전히 하나의 부품으로 만드는 것을 모듈화 라고 한다.