之前的博客有介绍JavaScript函数式编程的curry化,今天就介绍一个跟curry化有点像的偏函数(partial function)
先介绍一下什么叫偏函数,其实指的是将给定的函数的部分参数固定化,然后返回新的函数举个例子比如
这是数学里的多元函数,我们固定其部分参数,那么就可以得到新的函数,比如这种
仔细想想curry化,其实是一种特殊的偏函数,它固定参数的顺序只能是从左往右,然后返回新函数
了解了概念,我们来动手实现这个偏函数
给出多种实现方式(纯属自己无聊)
es5实现
//es5实现
function partial(fn){
var args = Array.prototype.slice.call(arguments); //将类数组对象arguments转为数组
args.shift(); //除去fn参数
for (var i = args.length;i<fn.length;i++) //补齐,跟fn的参数列表对应上
args.push(undefined)
return function() {
var remainArgs = Array.prototype.slice.call(arguments), // 剩余参数
index = 0;
for (i = 0; i < args.length; i++) {
args[i] === undefined && (args[i] = remainArgs[index++])
}
return fn.apply(this,args);
}
}
通过个Function添加原型链的方式实现 es5版
//通过个Function添加原型链的方式实现 es5版
Function.prototype.partial = function() {
var args = [].slice.call(arguments),
that = this;
for (var i = args.length;i<that.length;i++) //补齐,跟fn的参数列表对应上
args.push(undefined)
return function() {
var remainArgs = [].slice.call(arguments),
index = 0;
args.forEach(function(arg,i){
arg === undefined && (args[i] = remainArgs[index++])
})
return that.apply(this,args)
}
}
es6实现
//es6实现
const partial_es6 = (fn,...args) => {
for (let i = args.length;i<fn.length;i++) //补齐,跟fn的参数列表对应上
args.push(undefined)
return (...remainArgs) => {
let j = 0;
args.forEach((arg,i) => arg === undefined && (args[i] = remainArgs[j++]))
return fn(...args)
}
}
通过个Function添加原型链的方式实现 es6版
//通过个Function添加原型链的方式实现 es6版
Function.prototype.partial_es6 = function(...args){
for (let i = args.length;i<this.length;i++) //补齐,跟fn的参数列表对应上
args.push(undefined)
return (...remainArgs) => {
let j = 0;
args.forEach((arg,i) => arg === undefined && (args[i] = remainArgs[j++]))
return this(...args)
}
}
使用如下
function add4(a,b,c,d) {
return a + b + c + d;
}
var _add4 = add4.partial(1,undefined,3,undefined);
console.log(_add4(2,4)); // 1 + 2 + 3 + 4 = 10
那么偏函数还有啥用呢,再来个最简单的例子,比如setTimeout(fn,time)这个函数,那么我们可以固定后面的time参数,这样我们就可以得到很多时间间隔一样的setTimeout函数‘
var setTimeout_1s = partial(setTimeout,undefined,1000);
setTimeout_1s(function(){
//do something
});
setTimeout_1s(function(){
//do something
});
有了这个例子,剩下的应用读者可以自己想想