概念
柯里化(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');
- 每次调用都返回一个函数
- 参数传完则执行函数,并返回结果
【重点
】不断的合并新参数,达到总长度则执行函数
//使用参数长度(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');
网友评论