函数柯里化

作者: 前往悬崖下寻宝的神三算 | 来源:发表于2018-08-30 17:22 被阅读36次

概念


柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数的新函数

用处


  • 封装函数,减少需传入的参数数量(确定不变参数,减少可变参数)
  • 分步骤传参(语义化)

减少参数


需求:实现一个函数,返回一个由 域名 模块 接口名构成的字符串。

常规做法 :

//es6
let fn=(domain,module,name)=>domain+module+name;

//es5
function fn(domain,module,name){
  return domain+module+name;
}
//可能涉及本地开发和上线
//本地开发使用
fn('127.0.0.1','user','getUserInfo');
fn('127.0.0.1','production','getProductionInfo');
//换个ip使用
fn('112.36.25.45','user','getUserInfo');
fn('112.36.25.45','production','getProductionInfo');

如何避免每次使用都重复传入相同的参数呢?这时就可以使用柯里化来减少参数(确定不变参数,减少可变参数)

//es5
function fnWrap(){
  var argu1=Array.prototype.slice.call(arguments);
  return function(){
     var argu2=Array.prototype.slice.call(arguments);
     return fn.apply( argu1.concat(argu2) ); // fn在上以段代码里
  }
}

//本地使用
var localFn=fnWrap('127.0.0.1');
localFn('user','getUserInfo');
localFn('production','getProductionInfo');
//其他ip
var onlineFn=fnWrap('112.36.25.45');
onlineFn('user','getUserInfo');
onlineFn('production','getProductionInfo');
//本地user模块
var localUserFn=fnWrap('127.0.0.1','user');
localUserFn('getUserInfo');
localUserFn('getXX');

貌似封装的不错,进一步修改,给任何函数使用

  • 造轮子
    利用闭包存储参数
//es5
var curry=function(fn){
  var argu1=Array.prototype.slice.call(arguments,1);
  return function(){
    var argu=argu1.concat(Array.prototype.slice.call(arguments));
    return fn.apply(null,argu)
  }
}
  • 使用bind 【重点
    bind(ctx,argu1,argu2,...)
    bind函数实际就是个现成的柯里化函数,它接收形参并返回一个新的函数

使用举例

var localFn=curry(fn,'127.0.0.1');
localFn('user','getUserInfo');
var localFn1=fn.bind(null,'127.0.0.1');
localFn1('user','getUserInfo');

分步骤传参


如果你的函数fn参数太多怎么办?都放在一个对象里也无不可,但是显的太乱,如果能语义化自然最好。

var fnCurry=curry(fn);
fnCurry('127.0.0.1')('user')('getUserInfo');
  1. 每次调用都返回一个函数
  2. 参数传完则执行函数,并返回结果

重点】不断的合并新参数,达到总长度则执行函数

//使用参数长度(fn.length)判断参数是否传完
function curry(fn) {
    //记录fn和初始参数
    var initArgu=Array.prototype.slice.call(arguments,1);
    function _c(argu){
        //记录上一次累计参数
        if(argu.length===fn.length){
          return fn.apply(null,argu);
        }
        return function(){
            var _argu=Array.prototype.slice.call(arguments);
            //当前所有累计参数
            return _c(argu.concat(_argu));
        }
        
    }
    return _c(initArgu);
}

//es6实现
let curry=(fn,...initArgu)=>{
    let _c=(argu)=>{
        if(argu.length===fn.length){
            return fn(...argu)
        }
        return (..._argu)=>{
            return _c([...argu,..._argu])
        }
    }
    return _c(initArgu)
}

使用

var fnCurry=curry(fn);
fnCurry('127.0.0.1','user')('getUserInfo'); 

var fnCurry=curry(fn,'127.0.0.1');
fnCurry('user')('getUserInfo'); 

相关文章

网友评论

    本文标题:函数柯里化

    本文链接:https://www.haomeiwen.com/subject/xcypmftx.html