知食记
搜索文档…
柯里化2
用闭包把参数保存起来,当参数的数量足够执行函数了,就开始执行函数,有没有毛病

第一版

1
var curry = function (fn) {
2
// arguments[0]是fn, 这里是收集更多的参数
3
// 注意,arguments是array-like object,所以要用array的方法
4
var args = [].slice.call(arguments, 1);
5
return function() {
6
// 合并所有参数
7
var newArgs = args.concat([].slice.call(arguments));
8
return fn.apply(this, newArgs);
9
};
10
};
11
12
13
//应用
14
function add(a, b) {
15
return a + b;
16
}
17
18
var addCurry = curry(add, 1, 2);
19
addCurry() // 3
20
//或者
21
var addCurry = curry(add, 1);
22
addCurry(2) // 3
23
//或者
24
var addCurry = curry(add);
25
addCurry(1, 2) // 3
Copied!

第二版

1
function sub_curry(fn) {
2
var args = [].slice.call(arguments, 1);
3
return function() {
4
return fn.apply(this, args.concat([].slice.call(arguments)));
5
};
6
}
7
8
function curry(fn, length) {
9
10
length = length || fn.length;
11
12
var slice = Array.prototype.slice;
13
14
return function() {
15
if (arguments.length < length) {
16
var combined = [fn].concat(slice.call(arguments));
17
return curry(sub_curry.apply(this, combined), length - arguments.length);
18
} else {
19
return fn.apply(this, arguments);
20
}
21
};
22
}
23
24
// 应用
25
var fn = curry(function(a, b, c) {
26
return [a, b, c];
27
});
28
29
fn("a", "b", "c") // ["a", "b", "c"]
30
fn("a", "b")("c") // ["a", "b", "c"]
31
fn("a")("b")("c") // ["a", "b", "c"]
32
fn("a")("b", "c") // ["a", "b", "c"]
Copied!
更易懂的实现
1
function curry(fn, args) {
2
var length = fn.length;
3
args = args || [];
4
return function() {
5
var _args = args.slice(0), arg, i;
6
for (i = 0; i < arguments.length; i++) {
7
arg = arguments[i];
8
_args.push(arg);
9
}
10
if (_args.length < length) {
11
return curry.call(this, fn, _args);
12
}
13
else {
14
return fn.apply(this, _args);
15
}
16
}
17
}
18
java
19
20
var fn = curry(function(a, b, c) {
21
console.log([a, b, c]);
22
});
23
24
fn("a", "b", "c") // ["a", "b", "c"]
25
fn("a", "b")("c") // ["a", "b", "c"]
26
fn("a")("b")("c") // ["a", "b", "c"]
27
fn("a")("b", "c") // ["a", "b", "c"]
Copied!

超简洁写法

1
var curry = fn =>
2
judge = (...args) =>
3
args.length === fn.length
4
? fn(...args)
5
: (arg) => judge(...args, arg)
Copied!
参数不满足长度要求时,返回的函数仍需使用rest parameter:(...arg) => judge(...args, ...arg),否则除了第一次可以传递多个参数,后面只能一个一个传到足够为止了,不能直接处理fn(1,2)(3,4,5)的情况。

超超简洁写法

1
var curry = (fn, ...args) =>
2
fn.length <= args.length
3
? fn(...args)
4
: curry.bind(null, fn, ...args)
5
var fn = curry(function(a, b, c){
6
console.log([a,b,c])
7
})
8
9
fn(1,2,3)
10
fn(1,2)(3)
11
fn(1)(2,3)
12
fn(1)(2)(3)
13
14
// [ 1, 2, 3 ]
15
// [ 1, 2, 3 ]
16
// [ 1, 2, 3 ]
17
// [ 1, 2, 3 ]
Copied!