클로저(closures)
함수와 함수가 선언된 어휘적(lexical)환경의 조합을 말한다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.
출처: MDN
자바스크립트는 함수가 호출되는 환경과는 별개로 기존에 선언되어 있던 어휘적 환경을 기준으로 변수를 조회하려고 하는데,
외부 함수의 변수에 접근할 수 있는 내부 함수를 클로저 함수라고 한다.
클로저 함수
클로저는 외부 함수의 컨텍스트에 접근할 수 있는 내부 함수를 뜻합니다. 외부 함수의 실행이 종료된 후에도, 클로저 함수는 외부 함수의 스코프, 즉, 함수가 선언된 어휘적 환경에 접근할 수 있습니다.
const add = function(x) {
return function(y) {
return x + y;
}
}
위 함수의 리턴값은 함수의 형태이다. 즉, 함수를 리턴하는 함수인 것이다
클로저는 리턴하는 함수에 의해 스코프가 구분되는데 클로저의 핵심은 스코프를 이용해서 변수의 접근 범위를 닫는(closure)데에 있다.
따라서, 함수를 리턴하는 만큼이나 변수가 선언된 곳이 중요하다.
const add = function(x) {
return function(y) {
return x + y;
}
}
다시한번 동일한 예제에서 처음 등장하는 매개변수 x
는 가장 바깥쪽에 있으니 외부함수,
매개변수가 y
인 함수는 안쪽에 있으니 내부 함수라고 불렀을 때
1. 외부 함수는 y에 접근이 가능한가?
2. 내부 함수는 x에 접근이 가능한가?
1번의 답은 no이다. 바깥 스코프에서는 안쪽 스코프로의 접근이 불가하다.
2번의 답은 yes이다. 안쪽 스코프는 바깥 스코프에서 선언된 변수에 접근이 가능하다.
const makeCounter = () => {
let value = 0;
return {
increase: () => {
value = value + 1
},
decrease: () => {
value = value - 1
},
getValue: () => value
}
}
const counter1 = makeCounter();
클로저 모듈 패턴이라고 불리는 아주 유용한 패턴이다.
위 예제를 보면, makeCounter
라는 함수는 내부 함수를 단 하나 리턴하는 것에 그치지 않고 여러개의 내부 함수를 리턴하도록 객체에 담았다. 따라서 counter1
은 객체이다.
외부 스코프는 내부 스코프에 접근할 수 없다라는 규칙에 의해 value
값을 직접 수정하는것은 불가능하지만, 리턴하는 객체가 제공하는 메서드를 통해 value
값을 간접적으로 조작할 수 있는데 이것이 바로 정보의 접근 제한(캡슐화)이다.
만약 스코프로 value값을 감싸지 않았더라면 value
는 전역변수가 됐을 것이다. 하지만 위에서도 언급했듯 전역변수를 많이 만드는 건 그다지 좋은 일이 아니다.
이처럼, 함수 재사용성을 극대화하여 함수 하나를 완전히 독립적인 부품 형태로 분리하는 것을 모듈화라고 한다. 즉, 클로저는 데이터와 메서드를 묶어서 다룰 수 있기 때문에 모듈화에 유리하다.