函数柯西化(经典面试题)
// 实现一个add方法,使计算结果能够满足如下预期:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
function add() {
// 第一次执行时,定义一个数组专门用来存储所有的参数
var _args = Array.prototype.slice.call(arguments);
// 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
var _adder = function() {
_args.push(...arguments);
return _adder;
};
// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
_adder.toString = function () {
return _args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}
add(1)(2)(3) // 6
add(1, 2, 3)(4) // 10
add(1)(2)(3)(4)(5) // 15
add(2, 6)(1) // 9
加强理解版本
```js // v1: 实现一个精简版的curry函数 function curry(fn, ...args) { return function () { return fn.apply(this, args.concat([].slice.call(arguments))); } } function add(a, b) { return a + b; }
var addCurry = curry(add, 1, 2); console.log(addCurry());// 3 //或者 var addCurry = curry(add, 1); console.log(addCurry(2)); // 3 //或者 var addCurry = curry(add); console.log(addCurry(1, 2)); // 3
// v2: 上面的代码优化 function sub_curry(fn) { let args = [].slice.call(arguments, 1); return function () { return fn.apply(this, args.concat([].slice.call(arguments))); } }
function curry(fn, length) { length = length || fn.length; let slice = Array.prototype.slice;
return function () {
}
}
// 容易理解的版本 function curryFn(fn, args) { let length = fn.length; // 获取fn这个函数的参数数量 args = args || []; // 参数
return function () {
let _args = args.slice(0);
for (let i = 0; i < arguments.length; i++) {
_args.push(arguments[i]);
}
if (_args.length < length) {
return curryFn.call(this, fn, _args);
}
else {
return fn.apply(this, _args);
}
}
}
let fn = curryFn(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"] ```