Chapter 4. 함수 조립하기

남자김용준·2021년 5월 7일
0

함수형 자바 스크립트의 10가지 기법

  1. 함수를 되도록 작게 만들기
  2. 다형성 높은 함수 만들기
  3. 상태를 변경하지 않거나 정확히 다루어 부수 효과를 최소화하기
  4. 동일한 인자를 받으면 항상 동일한 결과를 리턴하는 순수 함수 만들기
  5. 복잡한 객체 하나를 인자로 사용하기보다는 되도록 일반적인 값 여러 개를 인자로 사용하기
  6. 큰 로직을 고차 함수로 만들고 세부 로직을 보조 함수로 완성하기
  7. 어느 곳에서든 바로 실행하거나 혹은 미뤄서 실행할 수 있도록 일반 함수이자 순수 함수로 선언하기
  8. 모델이나 컬렉션 등의 커스텀 객체보다는 기본 객체를 이용하기
  9. 로직의 흐름을 최대한 단방향으로 흐르게 하기
  10. 작은 함수를 모아 큰 함수로 만들기

고차 함수와 보조 함수

1. _.once

  • 한 번만 실행하는 함수
var hi = _.once(function(){
  console.log('hi');
});

hi();
// hi
hi();
// 아무 일도 일어나지 않음

2. skip

  • 다시 물어보지 않는 함수
function skip(body){
  var yes;
  return function(){
    return yes || (yes = body.apply(null,arguments));
  }
}
  • skip은 고차 함수이자 함수를 만드는 함수
  • 함수로 함수를 만들 때는 재료로 함수가 사용되기도 하고 일반 값이 사용되기도 한다.
  • 함수로 만들어진 함수는 대부분 클로저다.

부분 적용

1. _.partial로 함수 만들기

기본적인 _.partial 함수 사용법

var pc = _.partial(console.log,1);
pc(2);
// 1 2

var pc = _.partial(console.log,_,2);
pc(1);
// 1 2
pc(1,3);
// 1 2 3

var pc = _.partial(console.log,_,_,3);
pc(1);
// 1 undefined 3
pc(1,2);
// 1 2 3
pc(1,2,4);
// 1 2 3 4


var add_all = _.partial(_.reduce,_,function(a,b){ return a+b });
add_all([1,2,3,4]);
// 10
  • partial과 reduce는 함수를 다루는 고차 함수

2. .partial과 .compose로 함수 만들기

  • _.compose는 함수를 연속으로 실행해 주는 함수 (오른쪽의 함수를 실행한 결과를 왼쪽의 함수에게 전달하는 것을 반복하는 고차 함수)
_.compose(
  console.log, 
  function(a){return a-2;},
  function(a){return a+5;}
)(0);
// 0+5 -> 5-2 -> console.log
// 3

var falsy_value = _.compose(
  _.partial(_.isEqual,-1),
  _.partial(_.findIndex,_,_.identity)
);

console.log(falsy_value([1,true,{}]));
// false
console.log(falsy_value([0,1,false]));
// false
console.log(falsy_value([0,"",false]));
// true

var every = _.compose(
  _.partial(_.isEqual,-1),
  _.partial(_.findIndex,_,_.negate(_.identity))
);

console.log(every([1,true,{}]));
// true
console.log(every([0,1,false]));
// false
console.log(every([0,"",false]));
// false

연속적인 함수 실행

1. 체인의 아쉬운 점

  • 체인 객체가 가지고 있는 메서드만 이용할 수 있기 때문에체인 객체와 연관 없는 로직이나 다른 재료를 중간에 섞어 사용하기 어렵다.
  • 결과를 완성해 나가는 과정에서 체인을 끊어야 한다.

2. _.compose의 아쉬운 점

  • 함수 실행의 순서가 오른쪽에서부터 왼쪽이기 때문에 가독성이 떨어짐

3. 파이프라인

파이프라인은 .compose의 장점을 그대로 가진다.
.compose와 기본적인 사용법은 동일하나 실행 방향이 왼쪽에서 오른쪽, 위에서 아래로 표현된다.

// 마이클 포거스의 _.pipeline

_.pipeline = function(){
  var funs = arguments;
  
  return function(seed){
    return _.reduce(funs,
      function(l,r){ return r(l);},              
      seed);
  };
};

var div_square = _.pipeline(
  function(a){
    return a / 2;
  },
  function(a){
    return a * a;
  }
);

console.log(div_square(6));
// 9
  1. arguments를 지역 변수 funs에 담았다.
  2. funs를 기억하는 함수를 리턴한다.
  3. 리턴된 함수가 나중에 실행되면 받은 인자인 seed를 _.reduce의 마지막 인자로 넘겨 주어 seed는 최초의 l이 된다.
  4. 오른쪽 함수 r을 실행하며 왼쪽 함수의 결과 l을 넘겨주고 있다. funs의 개수만큼 반복되며 마지막 함수의 결과가 곧 _.pipeline으로 만든 함수의 결과가 된다.

_.pipeline은 작은 함수들을 모아 큰 함수를 만드는 함수
파이프라인은 클래스와 비슷한 역할을 대신할 수 있다.

var users = [];
var companies = [];

function joined_at(attrs){
  return _.extend(attrs,{joined_at: new Date()});
}

function greeting(member){
  return member.name + "회원님은 " + member.id + "번째 회원이십니다. 환영합니다.";
}

var join_user = _.pipeline(
  joined_at,
  function(member){
    users.push(member);
    member.id = users.length;
    return member;
  },
  greeting
);

var join_company = _.pipeline(
  joined_at,
  function(member){
    companies.push(member);
    member.id = users.length;
    return member;
  },
  greeting
);

더 나은 함수 조립

1. 함수 조립과 Partial.js

  • Underscore, Lodash 등의 주요 기능을 가지고 있고 좀 더 발전시킨 라이브러리

2. Partial.js의 _.pipe

위에서 설명했던 마이클 포거스의 .pipeline은 Multiple Results를 지원하지 않고, 파이프라인의 내부 함수에서 this를 사용할 수 없다.
Partial.js의 파이프라인 함수
.pipe는 Multiple Results와 this를 지원한다.

//정의 후 call을 통한 실행
_.pipe(
  function(){
    return this.a;
  },
  console.log,
  function(){
    this.b = 2;
    return this;
  },
  console.log
).call({a:1});

var obj = {
  a: 10,
  method1: _.pipe(
  			  function(){
                return this.a;
              },
    		  console.log,
    		  function(){
                this.b = 2;
                return this;
              },
    		  console.log
  			)
};
obj.method1();

3. 즉시 실행 파이프라인 _.go

.go는 .pipe의 즉시 실행 버전이다.

_.go(10,
    function(a){ return a / 2},
    function(a){ return a + 2},
    console.log);
// 7
profile
frontend-react

0개의 댓글