JavaScript函数式编程之偏函数(Partial Function)

    之前的博客有介绍JavaScript函数式编程的curry化,今天就介绍一个跟curry化有点像的偏函数(partial function)

先介绍一下什么叫偏函数,其实指的是将给定的函数的部分参数固定化,然后返回新的函数举个例子比如

                                                                     y = f(x1,x2,x3,...,xn)

这是数学里的多元函数,我们固定其部分参数,那么就可以得到新的函数,比如y1 = f(x1,x2=1,x3=1,...,xn=1)这种

仔细想想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
});

有了这个例子,剩下的应用读者可以自己想想

猜你喜欢

转载自blog.csdn.net/daydream13580130043/article/details/83793569