【设计模式必备知识】函数柯里化
说实话,函数柯里化我真的有点疑惑,一直没有想到合理的应用的场景,于是决定今天老子要吃掉这块肉 ,哼~ 接下来,我们一起来了解一下函数柯里化吧
函数柯里化的概念
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)
常用的函数柯里化的场景
柯里化常见的作用的是什么呢?常见的作用是:
- 参数复用
- 延迟运行
- 扁平化
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