前置知识:
问题:使用 JS 来实现一个无线累加函数 add,参考如下:
add(1); // 1
add(1)(2); // 3
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
// 以此类推
toString() 来实现
function add(a) {
// 使用闭包
function sum(b) {
a = b ? (b + a) : a;
return sum;
}
// 重写 toString 方法,只在最后一次调用
sum.toString = function() {
return a;
}
// 返回一个 sum 函数
return sum;
}
add(1)(2)(3)(4)
运行结果:
解析:
add
函数内部定义sum
函数并返回,实现了连续调用;sum
函数形成了一个闭包,每次调用进行累加值,再返回当前函数sum
;add()
每次都会返回一个函数sum
,直到最后一个没被调用。默认会触发toString
方法,所以这里重写toString
方法,并返回累计的最终值a
。
当 **add(1)**
时,返回了一个未被调用的 sum
函数,这时会执行 sum.toString
重写的方法,返回值为 a
。这时 sum
函数没有执行。
当 **add(1)(2)**
时,add(1)
返回了一个未被调用的 sum
函数,等价于 sum(2)
,这时会执行 sum
函数,形参为 2;add(1)(2)
等价于一个未被调用的 sum
函数,这时会执行 sum.toString
重写的方法,返回值为 a。
柯里化来实现多参累加
function add() {
// 1. 将所有参数转换为数组
let args = Array.prototype.slice.call(arguments)
// 2. 再次调用 add 函数,传递合并当前与之前的参数
let fn = function() {
console.log('fn 函数。。。')
let arg_fn = Array.prototype.slice.call(arguments)
return add.apply(null, args.concat(arg_fn))
}
// 3. 最后默认调用,返回合并的值
fn.toString = function() {
console.log('重写方法。。。')
return args.reduce((prev, cur) => prev + cur)
}
return fn
}
/* ES6 改写 */
function add() {
// 1. 将所有参数转换为数组
let args = [...arguments]
// 2. 再次调用 add 函数,传递合并当前与之前的参数
let fn = function() {
console.log('fn 函数。。。')
return add.apply(null, args.concat([...arguments]))
}
// 3. 最后默认调用,返回合并的值
fn.toString = () => args.reduce((prev, cur) => prev + cur)
return fn
}
add(1)(2)(3)(4)
运行结果: