今天记录一个经典的手写面试题,手写函数的柯里化示例。
先说一下函数的柯里化是什么样的效果,举个例子,对于计算长方体体积的函数,需要传长、宽、高三个变量,那么可以通过(fun为函数名)
fun(a,b,c)
一次性进行传参,而柯里化过后,便可以分多次进行传参,如:
fun(a,b)(c)
fun(a)(b)(c)
也可以获得相应的结果:
下面是实现的示例代码,这里还是以计算长方体体积的函数来举例:
1.先书写一个基本的,求体积的函数
function mainFun(a,b,c) {return a*b*c;
}
2.开始书写构造函数使之转换为柯里化的形式:
先书写一个基本的构造函数,接受的参数便是要转换的函数(mainFun),并在里面存放一个列表用于存放参数(参数):
function klh(fn) {let self = this;self.canshu = [];
}
ps:此时通过创建一个实例来看到此数组(看一下就行)
let shili = new klh(mainFun);
console.log(shili.canshu); // []
3.想要让创建出来的实例可以作为函数调用,须在构建函数中return一个函数以供调用传参(即接受长、宽、高),可参考下述代码中的注释(arguments可以获取到该函数接收到的参数)。
function klh(fn) {let self = this;self.canshu = [];return function() {console.log('我接收到了参数'+[...arguments].join(','))// 输出结果:我接收到了参数2,3return [...arguments].join(',');}
}let shili = new klh(mainFun);
console.log(shili(2,3)) // 调用return出的函数并输出返回值
// 输出结果:2,3
4.先这里根据接收到的参数分两种情况进行讨论,
第一是接受到的参数已足以计算长方体体积(即已接收到三个参数),此时直接调用示例中的fn函数并返回其返回值即可:
function klh(fn) {let self = this;self.canshu = [];return function() {// 存放并记录已经接收过的参self.canshu.push(...arguments)// 注此处可直接用函数.length获取其参数的长度,mainFun定义时要求接受a、b、c三大变量因此为3if(fn.length == self.canshu.length) {return fn(...self.canshu)}}
}let shili = new klh(mainFun);
console.log(shili(2,3,4))
// 输出结果:24
第二种情况就是接受到的参数少于3,后续还会再次调用并传参;此时可将函数自身(可使用arguments.callee直接获取自身)return出去并再次触发并接受参数并push到参数列表(canshu)中:
function klh(fn) {let self = this;self.canshu = [];return function() {self.canshu.push(...arguments)if(fn.length == self.canshu.length) {return fn(...self.canshu)} else {return arguments.callee;}}
}let shili = new klh(mainFun);
console.log(shili(2)(3,4))shili = new klh(mainFun);
console.log(shili(2)(3)(4)) //两结果均为24
至此便可以完成该需求!
完整代码:
// 函数柯里化function mainFun(a,b,c) {return a*b*c;
}function klh(fn) {let self = this;self.canshu = [];return function() {self.canshu.push(...arguments)if(fn.length == self.canshu.length) {return fn(...self.canshu)} else {return arguments.callee;}}
}let shili = new klh(mainFun);
console.log(shili(2)(3,4))
shili = new klh(mainFun);
console.log(shili(2)(3)(4))
希望本文会对您有所帮助~^_^