函数组合-洋葱代码杀手

284 阅读1分钟

作用

纯函数和柯里化函数很容易导致洋葱代码:h(g(f(x)))

如:获取数组的最后一个元素再转换成大写字母_.toUpper(_.first(_.reverse(array)))

通过函数组合可以避免洋葱代码。

代码案例

function compose(f,g){
  return function (value) {
    return f(g(value));
  }
}

function fisrt(arr){
  return arr[0];
}

function reverse(arr) {
  return arr.reverse();
}

let last = compose(fisrt,reverse);

console.log(last([1, 2, 3, 4]));

原理实现

function compose(...fns) {
  return function (value) {
    return fns.reverse().reduce(function (acc, fn) {
      return fn(acc);
    }, value);
  }
}

组合代码的调试

const console = require("console");

// 柯里化函数
function curry(fn){
  return function curried (){
    if(arguments.length<fn.length){
      return curried.bind(null, ...arguments);
    }else{
      return fn(...arguments);
    }
  }
}
// 组合函数
function compose(...fns) {
  return function (value) {
    return fns.reverse().reduce(function (acc, fn) {
      return fn(acc);
    }, value);
  }
}
// 打日志
const trace = curry(function(tag,v){
  console.log(tag,v);
  return v;
})

const split = curry(function(sp,s){
  return s.split(sp);
})
const join = curry(function (sp, arr) {
  return arr.join(sp);
})
const map = curry(function (fn, arr) {
  return arr.map(fn);
})

// 例子:将 hello word 转换成 HELLOW-WORD
let test = compose(join("-"), trace("before join--"), map(v=>v.toUpperCase()), trace("after split--"),split(" "));

console.log( test("hello word") );

扩展

loadsh-fp