Closure(클로저), Currying(커링)
Closure (클로저)
클로저는 한 마디로 '외부함수의 변수에 접근 가능한 내부함수'이다.
MDN 문서에서는 클로저를 이렇게 표현하고 있다.
A closure is the combination of a function and the lexical environment within which that function was declared. This environment consists of any local variables that were in-scope at the time the closure was created.
클로저는 함수와 함수가 선언된 '어휘적 환경의 조합'이다. 이 환경은 클로저가 생성된 시점의 유효 범위 내에 있는 모든 지역 변수로 구성된다.
여기서 '함수가 선언된 어휘적(lexical) 환경'이란 무엇일까?
자바스크립트는 함수가 호출되는 환경와 별개로, 기존에 선언되어 있던 환경 을 기준으로 변수를 조회한다. 쉽게 말하면 자신을 감싸고 있는 바깥 환경을 기준으로 변수를 조회하는 것이다. 그리고 이러한 기존의 환경이 바로 '어휘적 환경'이다. 이런 특성에 따라 클로저는 내부(inner) 함수가 외부(outer) 함수의 지역 변수에 접근할 수 있게 된다.
아래 코드를 살펴보면, innerFunction()이라는 안쪽에 위치한 함수는 outerFunction()이라는 외부 함수의 모든 변수에 접근 할 수 있다. 코드에는 없지만 더 큰 범위인 전역(Global)변수에도 접근이 가능하다. 이렇게 외부함수의 변수에 접근할 수 있는 내부함수를 클로저라고 한다.
Currying (커링)
커링 (Currying) 은 f(a, b, c)처럼 여러개의 인자를 한번의 호출로 처리하던 함수를 f(a)(b)(c)처럼 분리하여 인자를 하나씩만 받는 여러개의 함수로 만드는 기술이다. 다시 말해 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어서 각각의 함수가 인자를 받도록 하는 것이다.
[ 예시 ]
function sum(x){ return function(y){ return x+y; } } sum(2)(3); //5
그렇다면 커링은 왜 쓰는 것일까?
커링은 여러 인자 중 일부를 고정시켜 사용할 수 있다. 아래 예시를 보면 x값은 100으로 고정시켜서 sum100에 미리 할당해 두고, sum100(y)와 같은 형태로 사용하고 있다. 이렇게 한 인자는 값을 고정시키고, 다른 인자는 변하는 값으로 두고 싶을 때 커링은 유용하게 쓰일 수 있다.
let sum100 = sum(100); sum100(25); //125 sum100(50); //150
다른 예시 코드이다. html 태그를 추가해주는 tagMaker라는 함수인데, tag를 붙여준다는 동일한 기능을 수행하지만 h1, a, div...등 각각의 tag마다 다른 함수를 만들면 다른 태그를 만들어낼 수 있다. 즉, 기본적인 기능은 공통적으로 가지고 있지만 조금씩 다르게 커스터마이징할 기능이 있을 경우에 커링을 사용하면 관리하기도 편하고 효율적일 것 같다.
function tagMaker(tag){ let startTag = '<' + tag + '/>'; let endTag = '</' + tag + '>'; return function(content){ return startTag + content + endTag; } }
let h1Maker = tagMaker('h1'); h1Maker('jooing'); // <h1>jooing</h1> h1Maker('blog'); // <h1>blog</h1> let aMaker = tagMaker('a'); h1Maker('jooing'); // <a>jooing</a> h1Maker('blog'); // <a>blog</a>