在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
第一种方式
function curry(fn, args) {
// length表示fn的参数有几个
var length = fn.length;
args = args || [];
return function () {
var _args = args.slice(0),
arg,
i;
for (i = 0; i < arguments.length; i++) {
arg = arguments[i];
_args.push(arg);
}
if (_args.length < length) {
return curry.call(this, fn, _args);
} else {
return fn.apply(this, _args);
}
};
}
var fn = curry(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"]
其实这种形式并不是真正意义上的柯里化,因为他可以在一次执行可以传多个参数。而柯里化是将一个多参数的函数转换成多个单参数的函数。
第二种方式
function add() {
// 第一次执行时,定义一个数组专门用来存储所有的参数
let _args = Array.prototype.slice.call(arguments);
// 在内部声明一个函数,利用闭包的特性保存_args并收集所有的参数值
let _adder = function() {
_args.push(...arguments);
return _adder;
};
// 利用toString隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
_adder.toString = function () {
return _args.reduce(function (a, b) {
return a + b;
});
}
return _adder;
}
试一下
console.log(add(1, 2)(3)());
// 6
知识点:
如果直接输出一个被返回的函数,那么就会调用这个函数的toString方法获取到他的字符串形式,然后再输出,所以我们可以再toString这个方法中做一些操作,让它返回计算结果,这也就是为什么会输出6了。