前置知识:
问题:使用 JS 来实现一个无线累加函数 add,参考如下:
add(1); // 1add(1)(2); // 3add(1)(2)(3); // 6add(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)
运行结果:
