함수를 사용하다보면 지역 변수의 범위 때문에 어떤 변수를 원하는 곳에 사용하고 싶은데 그러기 힘들 때가 있다. 클로저 함수는 함수 내부에서 사용되는 변수를 저장하여 또 다시 사용할 수 있도록 하는 구조를 말한다.
// const adder = x => y => x + y
const adder = function (x) { // 외부함수
return function (y) { // 내부함수
return x + y;
}
}
const adder = function (x) {
return function (y) {
return x + y;
}
}
const add5 = adder(5); // 함수 실행이 끝나고 '5'라는 값은 사용가능하다!
add5(7) // 12 - 함수 실행이 끝난 범위이지만 정상적으로 작동한다!
add5(10) // 15
const tagMaker = tag => content => `<${tag}>${content}</${tag}>`
const divMaker = tagMaker('div');
divMaker('hello') // '<div>hello</div>'
divMaker('squirrel') // '<div>squirrel</div>'
const anchorMaker = tagMaker('a');
anchorMaker('get') // '<a>get</a>'
anchorMaker('acorn') // '<a>acorn</a>'
const makeCounter = () => {
let value = 0;
return { // 객체에 담아서 여러 함수들을 리턴하도록 만든다
increase: () => {
value = value + 1
},
decrease: () => {
value = value - 1
},
getValue: () => value
}
}
const counter1 = makeCounter();
counter1 // { increase: f, decrease: f, getValue: f }
여기서 스코프 규칙에 의해 value라는 변수에 값을 직접 할당하는 것은 불가능하다: 정보의 접근제한(캡슐화). 간접적으로 내부 함수를 통해 변화시킬 수만 있다.
let multiplyByFive = function() {
return function(y) {
return 5 * y;
}
}
let multiplyBy5
multiplyBy5 = multiplyByFive();
multiplyBy5(4);
언뜻보면 클로저를 사용하는 것으로 볼 수 있다. 함수 안에 함수가 return 되고 있기 때문이다. 하지만 외부함수에서 사용되고 있는 인자 또는 변수가 없기 때문에(외부함수의 컨텍스트라는 어휘적 환경이 없기 때문에) 클로저를 사용하고 있다고 볼 수가 없다.
즉, ⓐ함수 내부에서 함수를 선언하고, ⓑ외부 함수에서 변수를 선언 또는 인자로 할당 받아 ⓒ내부 함수에서 사용할 수 있도록 만들어진 환경 자체가 클로저이다. 그리고 그 내부 함수를 클로저 함수라고 부른다.
이해하고 사용하기가 어렵지만 굉장히 중요하고 유용한 문법이므로 꼭 복습, 복습, 여러 번 되새길 수 있도록 하자!
fine.