Open gogoend opened 4 years ago
搜罗了百度上关于柯里化的相关资料,无奈各种措辞过于高深(比如柯里化这三个字。。。)……我发现我已经晕了~~~这到底是什么玩意儿?
下面这个函数用于输出某人的个人信息。
// 基本函数
function baseLogInfo(name,gender,age){
console.log(`我叫${name},性别${gender},年龄${age}。`)
}
经过调用后的结果:
在这里,函数接受了一堆参数,参数信息依次填入字符串模板对应的地方。当然,类似这样传值可能稍有一些麻烦,每次执行该函数都需要输入一大堆参数,参数没法复用。
因此,此处进行一些调整,每次传入一个参数,执行后都可以返回一个函数;如果所传入参数数量已经足够,那么就执行最终的函数。
// 柯里化改写1
function curryLogInfo1(name){
return function(gender){
return function(age){
console.log(`我叫${name},性别${gender},年龄${age}。`)
}
}
}
经过调用后的结果:
我们在执行的时候不必传入全部参数,仅仅传入部分参数。
当传入部分参数时,返回一个函数,该函数用于接收接下来还未传入的其他参数。
当传入全部参数时,将会直接执行最终的函数。
上面的代码我们实现了logInfo
这个函数的柯里化,这里我们来对任何一个函数实现柯里化。我们发现,柯里化后函数执行的过程似乎就是一个函数参数不断传入,直到有了足够参数后再执行真实函数的过程。
因此,接下来我们开始编写这样一个柯里化函数的函数。
函数接收一个待柯里化的函数(下面简称fn)作为函数。
function curry( fn ) {
// ...
return function temp(){
// ...
}
}
首先我们记录一下fn接收多少个参数,这里用fn.length即可得到。
function curry( fn ) {
let len = fn.length
return function temp(){
// ...
}
}
然后我们需要记录下我们向函数中传入过的所有的参数。正如上面所说,参数数足够多时,直接执行fn,否则继续收集参数。
function curry( fn ) {
let len = fn.length
return function temp(){
let args = [ ...arguments ]
if(args.length>=len){
// 参数足够多,可以执行
return fn( ...args )
} else {
// 参数不够,继续返回一个包含之前已接受到参数的函数,收集余下的参数
return function(){
// args:当前已接收过的参数
// arguments:新传入的参数
temp( ...args, ...arguments )
}
}
}
}
在这里我们可以注意一下函数收集参数的方式。这里有些相当于函数的递归调用,args
是包含当前temp函数已接收过的参数,参数不够时我们返回的函数中递归调用了temp函数,同时将已有参数以及新的参数传入,下次调用时即可在args
里取到所有参数。
有点意思
函数柯里化,这个词有时经常听说,一直想看,但有时却总是想不起来,直接就忘了这茬;
今天想起来,就还是在这里记一下吧,万一有用呢~
参考资料
https://www.zhangxinxu.com/wordpress/2013/02/js-currying/