Closure와 Currying

이효범·2022년 4월 27일
0

ES6 - OOP & FRP

목록 보기
14/15
post-thumbnail

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. 세율을 적용한다.

profile
I'm on Wave, I'm on the Vibe.

0개의 댓글