实现函数柯里化,最后返回柯里化函数的时候为什么不需要额外传参?
在学习函数柯里化的时候看到这篇文章 https://github.com/yygmind/bl...,
作者的一个实现思路是这样的:
function currying(fn, length) {
length = length || fn.length; // 注释 1
return function (...args) { // 注释 2
return args.length >= length // 注释 3
? fn.apply(this, args) // 注释 4
: currying(fn.bind(this, ...args), length - args.length) // 注释 5
}
}
// Test
const fn = currying(function(a, b, c) {
console.log([a, b, c]);
});
fn("a", "b", "c") // ["a", "b", "c"]
fn("a", "b")("c") // ["a", "b", "c"]
fn("a")("b")("c") // ["a", "b", "c"]
fn("a")("b", "c") // ["a", "b", "c"]
底下有一个评论说,"可以不用在递归 currying 的时候传入 length - args.length,因为 bind 返回的函数的 length 已经是 length - args.length 了",他给出的代码是:
function currying(fn) {
return function (...args) {
return args.length >= fn.length
? fn.apply(this, args)
: currying(fn.bind(this, ...args))
}
}
为什么bind后返回的函数的形参个数,即length刚好是length - args.length呢?
这个length - args.length 我的理解是计算还需要多少个参数才可以实际运算fn,第一次递归后,currying的第二个参数就是这个差值,不再是函数形参个数,之后拿这个差值与柯里化后的函数实际接受的参数数目比较,如果这个数目达到了差值,就不需要再递归了。而按照这个评论的说法, bind 返回的函数的length就是length - args.length,因此不需要给递归的currying传length - args.length,这是怎么看出来的?bind的第二个参数会在bind返回的函数实际执行的时候传递给它,基于这一点我们才可以收集参数,最后统一运算,但是为什么bind返回的函数的length就刚好是length - args.length呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
function.prototype.bind
bind 方法设置了返回的函数对象的 length 为 (输入的)fn.length - args.length
bind的时候args展开的是实参,数量当然就是传入的实参数量。
这种写法只适用于es6,es5以前还是需要第一种写法。(虽然第一种写法也用到了参数展开,但是可以很容易改写成非展开的写法,而第二种则依赖于展开操作的副作用)