【设计模式必备知识】函数柯里化

 说实话,函数柯里化我真的有点疑惑,一直没有想到合理的应用的场景,于是决定今天老子要吃掉这块肉 ,哼~  接下来,我们一起来了解一下函数柯里化吧

 函数柯里化的概念

  curring又称作为部分求值,一个curring的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另一个函数,

刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

下面例子为,每天计算开销,月底进行结算, 这个只要用于保存参数,或者判断是否需要进行一次性求值.

var cost = (function () {
  var args = [];
  return function () {
    if (arguments.length === 0) {
      var money = 0;
      for (var i = 0, l = args.length; i < l; i++) {
        money += args[i]
      }
      return money;
    }
    else { 
      Array.prototype.push.apply(args, arguments)
    }
  }
})()
cost(200)
cost(300)
cost()//500

接下来我们编写一个通用的function curring(){},该函数接收一个参数,即将要被curring的函数。
var curring = function (fn) {
  var arg = [];
  return function () {
    if (arguments.length === 0) {
      return arg
    }
    else {
      [].push.apply(arg, arguments);
      return arguments.callee // arguments.callee(代表当前正在执行的函数)
} } }; 
var cost = (function() {
  var money = 0
  return function() {
    for (var i = 0, l = arguments.length; i < l; i++) {
      money += arguments[i]
    }
    return money
  }
})()
var cost = curring(cost)
cost(300)     

 uncurring的概念

在javaScirpt中,当我们调用对象的某个方法时,其实不用去关心该对象原本是否被设计为拥有这个方法,这是动态类型的特点,也是常说的鸭子类型思想

一个对象未必只能使用它自身的方法,我们可以使用 call和aplly借用其他不属于自己的方法。

让类数组去借用Array.prototype的方法,是call和apply的常见的应用 ,

这是call和apply的最常用的场景之一

(function() {
    Array.prototype.push.call(arguments,4)
  console.log(arguments) } )(1,2,3)

我们可以把泛化this的过程提取出来,那么uncurrying 

Function.prototype.uncurrying = function () {
  console.log(this)//谁调用指向谁
  var self = this;
  return function () {
    var obj = Array.prototype.shift.call(arguments);//传入参数为对象
    return self.apply(obj, arguments)//传入参数为数组
  }
};
var push = Array.prototype.push.uncurrying();

(function () {
  push(arguments, 4);
  console.log(arguments,'arguments');
})(1, 2, 3)  

常用的函数柯里化的场景

柯里化常见的作用的是什么呢?常见的作用是:

  1. 参数复用
  2. 延迟运行
  3. 扁平化
var curry = function (fn) {
  var args = [].slice.call(arguments, 1)
  console.log(args,arguments)
  return function () {
    var newArgs = args.concat([].slice.call(arguments))//这句话有什么存在的意义????
    console.log([].slice.call(arguments),"argssssss")
    console.log(newArgs,"newArgs")
    return fn.apply(this, newArgs)
  }
};
function add(a, b) {
  return a + b
};

var addCurry = curry(add, 1, 2);
addCurry(); // 3

  

原文地址:https://www.cnblogs.com/Ewarm/p/11928939.html