es6
Closure와 Currying


Closure에 대해 간략히 알아본다.
Closure
데이터의 스코프 내의 특정한 변수의 값을 각인시켜놓는 것을 클로져라고 한다.
const createAdder = (x) => { return (y) => x + y; // 함수의 결과값으로 함수가 사용될 수 있다 } const add3 = createAdder(3); console.log('add3(2): ', add3(2)); // add3(2): 5
클로저를 이용한 연습 문제를 하나 풀어보자.
const request = (options) => { return fetch(options.url, options) .then(res => res.json()); }; const userPromise = request({ url: '/users', headers: { 'X-Custom': 'myKey' } }) const tasksPromise = request({ url: '/tasks', headers: { 'X-Custom': 'myKey' } }) // userPromise();
위의 코드를 클로져를 이용하여 리팩토링 해보도록 하자.
Object.assign 을 사용하도록 한다.
const request = (options) => { return fetch(options.url, options) .then(res => res.json()); }; const createRequester = (options) => { return (otherOptions) => { return request(Object.assign( {}, options, otherOptions )); }; }; const customRequest = createRequester({ headers: { 'X-Custom': 'myKey' } }); const userPromise = customRequest({ url: '/users', }) const tasksPromise = customRequest({ url: '/tasks', }) // userPromise();
위 리팩토링한 코드의 구조는 맨 위에서 첫번째 클로져의 예시로 든 코드의 구조와 동일하다.
Currying
클로져의 가장 기본적인 형식은 다음과 같다.
function add(x) { return function(y) { return x + y; }; };
이를 Fat arrow 방식으로 바꾼 형태는 다음과 같다.
const add = x => y => x + y;
근데 위 모양을 보면 Fat arrow가 연속적으로 두 개가 이어져 있는 형태이고 argument 두 개가 연속적으로 전달되는 형태이다.
위의 request 또한 Fat arrow 방식으로 바꾼 형태는 다음과 같다.
const request = defaults => options => { options = Object.assign( {}, defaults, options ); return fetch(options.url, options) .then(res => res.json()); };
위의 예시들처럼 두 개의 Fat arrow가 연속적으로 이어져 있는 형태를 Currying 이라고 한다.
Piecing it together
실제 사용되는 Closure와 Curring 의 예를 살펴보도록 한다.
// shopping mall, items, discounts, tax // url: '/cart/items' const items = [ // 장바구니 목록 { price: 100, name: 'shoes', weight: 10, size: 30 }, { price: 50, name: 'clothes', weight: 10, size: 30 }, { price: 30, name: 'toy car', weight: 10, size: 30 }, { price: 150, name: 'water', weight: 10, size: 30 }, ]; // total amount const map = fn => array => array.map(fn); const multifly = x => y => x * y; const pluck = key => object => object[key]; const tax = multiply(1.1); const discount = multifly(0.98); const customRequest = request({ headers: {'X-Custom': 'myKey'} }); customRequest({url: '/cart/items'}) .then(map(pluck('price'))) // [100, 50, 30, 150] .then(map(discount)) // [98, 49, 29.5, 147] .then(map(tax))
위의 코드는 클로져와 Curring을 이용하여
1. items, 즉 장바구니 데이터를 가져오고
2. 전체 장바구니에 들어있는 각 오브젝트로부터 price에 대응하는 숫자들을 뽑아서 리스트를 구성하고
3. 각 숫자에 discount를 적용한다.
4. 세율을 적용한다.