文章之前要声明, 本人刘艳龙博客全部来之原创。对您有没有价值看您给没给推荐。------ 一个程序菜鸟8月10日记
函数柯里化:柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。是否有些不太懂?好吧,用段代码来解释下。
function saySTS(something) {
return function(someboby) {
alert(something + "!" + sombody);
}
}
saySTS函数就是用来说些什么(something)对某人(somebody);这就是柯里化的函数。
-------------------------------------------------------------------------------------------------------------------------------------------------------
我们来看下如果不用柯里化来怎么实现。
function saySTS(something, somebody){
alert(something + "!" + sombody);
}。
--------------------------------------------------------------------------------------------------------------------------
也许你会问我函数柯里化到底有什么用,不就是把多个参数的函数转换成多个单参数函数吗?下面我拿实际前端开发中的例子来解释。
现在有这么一个问题模型:
你要开发一个抽奖活动页面,后台开发人员要跟您定一个抽奖接口,这个接口会根据不同的抽奖选项返回不同的抽奖信息。请求的接口的几个地址:"action.do?state=0","action.do?state=1","action.do?state=2".
假如这些接口是根据3种不同积分,来进行相应的抽奖活动,30积分抽奖的奖品,60积分抽奖的奖品,120积分抽奖的奖品,返回的接口可能是{中奖信息,抽奖剩余分数,中奖纪录,抽了多少次奖,剩余抽奖次数等等}。
此时你前端有6处需要根绝返回的接口数据进行显示或者交互操作,简化一点div#01, div#02, div#03, div#04, div#05, div#06.这几块要显示剩余的抽奖次数。
如果不用柯里化我会这样做
function render(url) {
$.ajax({
type:"post",
url:url,
cache:false,
async:true,
dataType:"json",
data:params,
//当异步请求成功时调用
success: function(data, status){
//此行可能你还需要对数据进行一些处理。总之在你拿数据渲染你的dom节点前或许还要做点别的。
$("div#01").html(data.times);//例子比较简单,可能你需要做的不只这些还有很多。抽奖的提示信息。
//等等其他操作.......
},
//当请求出现错误时调用
error: function(err){
alert("error : "+err);
}
})
}
很显然这样的代码耦合性很强,不太利于扩展跟维护.而且返回的数据我也不一定非得做html(data.times)这样的操作。把返回后的信息全部集中处理,这样很差。
改进下我们把成功之后的要处理的操作单独提取出来放在一个我们都会叫出来的名字callback
function callback(item, data) { //终于把耦合的代码搞出来了,item可能是div#01, div#02, div#03, div#04, div#05, div#06
$(item).html(data.times);
}
//这里我们假设后台人员只开发了一个接口,以至于我想查询剩余次数显示在相应的信息栏上也要返回(最近中奖纪录,剩余分数等)这些数据
//当然这是很失败的接口,一般接口只需要返回前端想要的数据即可。
function callback02(item, data) { //也许我也想做callback02这样的操作等,render都是可以支持的
return function(data){
$('item').click(function(e){
alert(data.gift);
})
}
}
function render(url, item, callback) {
$.ajax({
//一些代码不重复
success: function(data, status){
//此行可能你还需要对数据进行一些处理。总之在你拿数据渲染你的dom节点前或许还要做点别的。
callback(item, data);
},
error: function(err){
alert("error : "+err);
}
})
}
这样我们就可以对div#01 div#02 等要操作的dom节点灵活的,而且操作方式可以多变化。
但是有一天突然要做这么一件事儿,我不光要显示剩余次数,而且还要把礼品等等一切信息在前端显示出来
function callback03(data) { //这个过程不仅仅想知道msg或者gift
//针对一个前端抽奖模块进行全面的渲染。
//不同的几个前端模块我要显示所有关于本人中奖的信息(抽中多少次,中过什么奖啊等等)
}
等等,我们的render函数有三个参数,这个callback03是不是不符合规定啊,我们还需要item
因为render里面的callback我们是这样调用的callback(item, data);
很显然render已经不适合新的callback03了,再写一个差不多的render?重复很多代码只是在callback(item, data)有些不一样的新的处理函数?
不,显然不需要,我们不能这样做,这是很冗余的。那我们怎么办?
您可能在想:come on!My man(丹泽尔华盛顿在美国黑帮的一句口头禅,很是喜欢),来点正题吧!
好吧,来个柯里化过的函数吧。
首先改变render函数改成更灵活的。让他专注于做一件事。就是处理callback,不要加上item。
function render(url, callback) {
$.ajax({
//一些代码不重复
success: function(data, status){
//此行可能你还需要对数据进行一些处理。总之在你拿数据渲染你的dom节点前或许还要做点别的。
callback(data);
},
error: function(err){
alert("error : "+err);
}
})
}
可是callback, callback02我的这两个小伙伴们怎么办? 如果你给改了他们两个要怎么办?因为render已经不支持他们了。
别急,我们把这两个小伙伴们打扮下。
function update(item) {
return function(data) {
$(item).html(data);
}
}
function update02(item) {
return function(data){
$('item').click(function(e){
alert(data.gift);
})
}
}
function render(url, callback) {
$.ajax({
//一些代码不重复
success: function(data, status){
//此行可能你还需要对数据进行一些处理。总之在你拿数据渲染你的dom节点前或许还要做点别的。
callback(data);
},
error: function(err){
alert("error : "+err);
}
})
}
render("action.do?state=0", update("div#01"));
render("action.do?state=0", update("div#02"));
render("action.do?state=0", update02("div#01"));
render("action.do?state=0", update02("div#02"));
柯里化是函数式编程重要标志,这个demo借助匿名和闭包完成了函数柯里化,函数式编程一切皆为函数。函数式编程灵活性和执行效率很高,但是整体逻辑不太好捋。
希望大家能提出一些自己的建议。