JS 浅谈函数柯里化,不明觉厉

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。

柯里化函数思想

函数柯里化(function currying)又称部分求值。一个currying的函数首先会接受一些参数,接受了这些参数后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包里被保存起来。待到函数真正需要求值的时候,之前传入的参数都会被一次性用于求值。

假设我们要编写一个计算每月开销的函数。在每天结束之前,我们都要记录今天花了多少钱,代码如下:

let result = 0;
let add = function(num){
  result += num;
  console.log(result);
}
add(10); // 10
add(5); // 15
add(8); // 23

这段代码在每天结束后都会记录并计算到今天为止花了多少钱,但我们不太关心每天花掉多少,只想知道月底总共花掉了多少,也就是说,只需要在月底计算一次。

如果在每个月的前二十九天,我们都只是保存好当天的开销,直到第30天才进行求值计算,这就达到了我们的目的。

柯里化实现

  • 当函数调用有参数时,保存参数,作为下次调用的参数
  • 当函数调用无参数时,计算结果

最终,我们要实现这样的方案,curry函数可以多次调用,每次调用的参数不定;当函数调用无参数时,输出最终结果

// curry - 柯里化函数
// fn - 计算结果的函数
// args - 参数
curry(fn, args...)(args...)(args...)(); 

废话不多说,直接上代码:

let add = function(){
  let args = Array.prototype.slice.call(arguments);
  let result = 0;
  args.forEach((item, key)=>{
    result += item;
  })
  console.log(result);
  return result;
}

let curry = function(fn){
  let args = Array.prototype.slice.call(arguments, 1);
  return function(){
    let args_add = Array.prototype.slice.call(arguments);
    let newArgs = args.concat(args_add);
    if(args_add.length){
      // 当函数调用无参数时,计算结果
      return curry.call(null, fn, ...newArgs);
    }else{
      // 当函数调用有参数时,保存参数,作为下次调用的参数
      return fn.apply(null, newArgs);
    }
  }
}

curry(add, 1, 2)(4, 5)();  // 12

柯里化意义

1、延迟计算。(就像烹饪一样,食材全部准备好后,厨师才开始做菜)

2、参数复用。当在多次调用同一个函数,并且传递的参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。

3、动态创建函数。这可以是在部分计算出结果后,在此基础上动态生成新的函数处理后面的业务,这样省略了重复计算。或者可以通过将要传入调用函数的参数子集,部分应用到函数中,从而动态创造出一个新函数,这个新函数保存了重复传入的参数(以后不必每次都传)

 

欢迎大家指正喽,哈哈

posted @ 2018-08-21 19:24  狂奔的小马扎  阅读(583)  评论(0编辑  收藏  举报