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();
위 리팩토링한 코드의 구조는 맨 위에서 첫번째 클로져의 예시로 든 코드의 구조와 동일하다.
클로져의 가장 기본적인 형식은 다음과 같다.
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 이라고 한다.
실제 사용되는 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. 세율을 적용한다.