柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。
函数柯里化 不仅仅是提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性。
函数柯里化的通用实现:
function curring(fn){
var slice=Array.prototype.slice,
_args=slice.call(arguments,1);
return function(){
var __inargs=slice.call(arguments);
return fn.apply(null,_args.concat(__inargs));
}
}
// 原始的加法函数
function origPlus(a, b) {
return a + b;
}
// 柯里化后的plus函数
function plus(a) {
return function(b) {
return a + b;
}
}
// ES6写法
const plus = a => b => a + b;
复制代码
柯里化
- 就是一个部分配置多参数函数的过程
- 每一步都返回一个接受单个参数的部分配置好的函数。
应用场景:
- 提高适用性: 【通用函数】解决了兼容性问题,但同时也会再来,使用的不便利性,不同的应用场景往,要传递很多参数,以达到解决特定问题的目的。有时候应用中,同一种规则可能会反复使用,这就可能会造成代码的重复性。
看下面一个例子: function square(i) { return i * i; }
function dubble(i) {
return i *= 2;
}
function map(handeler, list) {
return list.map(handeler);
}
// 数组的每一项平方
map(square, [1, 2, 3, 4, 5]);
map(square, [6, 7, 8, 9, 10]);
map(square, [10, 20, 30, 40, 50]);
// ......
// 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5]);
map(dubble, [6, 7, 8, 9, 10]);
map(dubble, [10, 20, 30, 40, 50]);
复制代码
例子中,创建了一个map通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square和dubble。
应用中这种可能会更多。当然,通用性的增强必然带来适用性的减弱。但是,我们依然可以在中间找到一种平衡。
-
柯里化改造
function square(i) { return i * i; } function dubble(i) { return i *= 2; } function map(handeler, list) { return list.map(handeler); } var mapSQ = currying(map, square); mapSQ([1, 2, 3, 4, 5]); mapSQ([6, 7, 8, 9, 10]); mapSQ([10, 20, 30, 40, 50]); // ...... var mapDB = currying(map, dubble); mapDB([1, 2, 3, 4, 5]); mapDB([6, 7, 8, 9, 10]); mapDB([10, 20, 30, 40, 50]); // ...... 复制代码
-
固定易变因素:
- 柯里化的特性决定了他的应用场景,提前把易变因素通过传参固定下来,生成一个更加明确的函数。典型应用是bind()函数,用以固定this这个易变对象;
talk is cheap,show me the code:
Function.prototype.bind=function(context){ // 引用this 对象; var _this=this, _args=Array.prototype.slice.call(arguments,1); // 获取当前传参数组; return function(){ return _this.apply(context,_args.concat(Array.prototype.slice.call(arguments))); } } 复制代码
-
延迟执行:
-
不断的柯里化,累计传入的参数,最后执行;
var add = function() { var _this = this, _args = arguments return function() { if (!arguments.length) { var sum = 0; for (var i = 0, c; c = _args[i++];) sum += c return sum } else { Array.prototype.push.apply(_args, arguments) return arguments.callee } } 复制代码
}
add(1)(2)(3)(4)();//10 复制代码
通用写法:
var curry = function(fn) { var _args = [] return function cb() { if (arguments.length == 0) { return fn.apply(this, _args) } Array.prototype.push.apply(_args, arguments); return cb; } 复制代码
}
-