函数柯里化不仅极大地提高了代码的可复用性与灵活性,而且降低了代码的耦合性,但是在生产环境中使用时发现了美中不足的一点,遂有此文,目的是改造柯里化函数结构,使之更方便使用、易于理解。
为方便理解,本篇文章虚拟了一个简单的业务场景:更新指定栏目下指定节目的描述信息
普通的函数柯里化
首先,在变型前,一起看看大部分函数柯里化的实现与使用:1
2
3
4
5
6
7
8
9let updateProgramDesc = colunmID => {
return programID => {
desc => {
// do something...
}
}
}
// 使用方法,更新 ID为10的栏目 下 ID为1000的节目 的描述信息为’description content.‘
updateProgramDesc(10)(1000)('description content.');
变型初衷
使用时很明显,每一层的函数在传参的时候很容易让人产生困惑:
- 所使用的柯里化后的函数参数传到的哪一个层级?
- 该传入哪个参数了?
- 传入的这个参数是干什么的?
尤其在柯里化程度较高的情况下这种困扰尤为明显,使用时经常需要仔细观察上下文,甚至是去查看原函数来确定传参:1
func(param1)(param2)(param3)(param4)(param5)(param6);
柯里化的变型
出于以上初衷,对柯里化函数的结构做了一些调整,如下:1
2
3
4
5
6
7
8
9
10
11let updateColumn = colunmID => {
return {
program(programID) {
return {
desc(desc) {
// do something...
}
}
}
}
}
发现哪里不同了吗?
下面是变型后的使用方法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// Fully chain calls.
updateColunm(10).program(1000).desc('description content.');
// Partial application invoke.
let column = updateColunm(10);
column
.program(1001)
.desc('update the description of program 1001 in column 100.');
column
.program(1002)
.desc('update the description of program 1002 in column 100.');
let program = column.program(1003);
program.desc('update the description of program 1003 in column 100.');
program.desc('update the new description of program 1003 in column 100.');
优点 & 不足
优点
通过return
object
代替function
的方式,对象名可以非常恰当地对当前传参进行描述,使用时更清晰易懂,不易造成使用时确定传参困难、传参错误等情况。
其实实现思想很简单吧~
不足
不过这种方法也有一个不足之处就是会增加少量代码与缩进,不过可以尝试使用Promise
来实现,会更优雅自然~
进一步可能
updateDesc(desc).ofProgram(programID).inColumn(columnID);
发现了吗?可以写出更贴近自然语言的柯里化函数!
不过前文没有这么做,你知道是为什么吗?
灵感来源
jQuery
的链式函数调用~
参考文档:
所有文章非特别说明皆为原创。技术更迭迅猛,部分内容可能会作修改,为保证信息与源同步,转载时请务必注明文章出处!谢谢合作 :-)A Beginner’s Guide to Currying in Functional JavaScript
Higher-Order Functions in JavaScript
JavaScript函数柯里化的一些思考