java中函数的作用是什么意思_javascirpt中偏函数的作用

要跪了,写了半天发现自己研究的原来根本不是柯里化,而是偏函数,被国内很多资料误导了,关于柯里化与偏函数的区别请看这里

http://stackoverflow.com/questions/218025/what-is-the-difference-between-currying-and-partial-application

关于偏函数的目的和作用一直很模糊,网上的资料很多都没有说到重点,大部分只关注于如何实现偏函数,而对其用途闪烁其词,直到最近看了这里:

个人认为所有写代码的技巧目的只有两个:一是提高程序性能,而是使代码模块化,减少耦合增强其可维护性。偏函数的作用很明显是属于第二种。经过偏函数之后,函数的通用性有所降低,但是适用性有所提高。

偏函数并没有我们想象中那么高深,其实我们经常在不知不觉中使用了偏函数,只是你没有发觉而已,让我们举个例子来看偏函数是的用途和如何演变为通用形式的。(关于偏函数的定义请自行百度或者查看我上面给出的链接)

偏函数的演变

假如现在我们基于某个sdk开发一个app,需要调用该sdk提供的api,这些api都有3个参数,分别是调用你的app的id,用户的id和用户的nickname(这个场景在hybrid式的webApp开发很常见)

api1( "myApp", "xiaoming", "小明");

api1("myApp", "xiaohong", "小红");

api1("myApp", "xiaogang", "小刚");

这时候你可能发现了一些端倪,代码中出现了重复的部分(你的app的id),这时候重构代码把公共的部分抽取出来,你可能会这么封装

let myApi1 = function(uid, nickname){

api1("myApp", uid, nickname);

}

myApi1("xiaoming", "小明");

myApi1("xiaohong", "小红");

myApi1("xiaogang", "小刚");

然后你继续开发,发现要调用另外一个api,这个api跟上面那个很相似,只是第2、3个参数变为了用户的令牌和用户id。因为你的app的id是不变的,有了之前的经验,你或许会这么封装。

let myApi2 = function(token, uid){

api2("myApp", token, uid);

}

myApi2("token1", "xiaoming");

myApi2("token2", "xiaohong");

myApi2("token3", "xiaogang");

继续开发的时候,你很有可能会继续调用类似的api3,api4,api5......,这些api的第一个参数都是你的app的id,而在你的某个项目里面,这都是固定不变,那么你的程序里面会出现类似的封装,可以看出又有了重复的代码

let myApi3 = function(p1, p2){

api3("myApp", p1, p2);

}

let myApi4= function(p1, p2){

api4("myApp", p1, p2);

}

let myApi5= function(p1, p2){

api5("myApp", p1, p2);

}

....

此时你或许会这么封装去减少重复

let getMyApi = function(api){return function(p1, p2){

api("myApp", p1, p2)

}

}

let myApi1 = getMyApi(api1)

let myApi2 = getMyApi(api2)

let myApi3 = getMyApi(api3)

一切看起来很好,但是很快又碰到了其它问题,你碰到了另外一种类型的api,它也是3个参数,第1个参数是app的id,第2个参数是你的app的名字,两个参数都是固定不变的,那么根据上面封装经验,你可能会这么封装:

let getMyApi2 = function(api){return function(p2){

api("myApp", "myAppName", p2)

}

}

let myApi4 = getMyApi2(api4)

let myApi5 = getMyApi2(api5)

let myApi6 = getMyApi2(api6)

这时你会发现 getMyApi 和 getMyApi2 似乎有一些相似的地方,它们都是:

1,将需要调用的api(一个函数)作为第1个参数传入

2,然后固定住部分不变的参数

3,然后返回新的函数

既然有相似的地方,说明还可以做进一步的抽象,我们可以这么写

let generalGetMyApi = function(api) {//把函数和需要固定住的参数都传递进来

let settledArgs = [].splice.call(arguments, 1);//返回一个新的函数,这个函数包含了已经固定住部分参数,并且传入一些易变的参数

return function() {//将不变的参数和易变的参数重新传进这个函数再执行

let mutableArguments =arguments;

api.call(null, [].concat.apply(settledArgs, mutableArguments));

}

}

以上就是一个简单的通用的偏函数的做法,有了这种做法,上面我们重构的问题都非常好解决了

当遇到第一种类型的api(第1参数需要固定),那么可以这样做

let myApi1 = generalGetMyApi(api1, "myApp1");

myApi1("xiaoming", "小明");

myApi1("xiaohong", "小红");

myApi1("xiaogang", "小刚");

let myApi12 = generalGetMyApi(api2, "myApp1");myApi2("token1", "xiaoming");myApi2("token2", "xiaohong");myApi2("token3", "xiaogang");

当遇到第二种类型的api(第1、2参数需要固定),那么可以这样做

let myApi3 = generalGetMyApi(api3, "myApp1","nameOfApp1");

myApi2("other args1")

myApi2("other args2")

myApi2("other args3")

现在代码没有了重复的味道,并且函数generalGetMyApi还可以在其它项目中复用。这就是偏函数的目的,将函数的通用性降低,提高了函数的适用性,而这一些是通过缓存部分参数实现的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值