柯里化的概念大家應該都清楚,就是將一個接受多個引數的函式轉化為接受單一引數的函式的技術。
原始碼位於 github.com/llh911001/m…
柯里化函式:
function inspect(x) {
return (typeof x === `function`) ? inspectFn(x) :inspectArgs(x);
}
function inspectFn(f) {
return (f.name) ? f.name : f.toString();
}
function inspectArgs(args) {
Array.prototype.slice.call(arguments, 0);
return [].slice.call(args, 0).reduce(function(acc, x){
return acc += inspect(x);
}, `(`) + `)`;
}
function curry(fx) {
// 函式的length屬性返回函式必須傳入的引數個數
var arity = fx.length;
return function f1() {
var args = Array.prototype.slice.call(arguments, 0);
// 引數個數滿足的處理
if (args.length >= arity) {
return fx.apply(null, args);
}
else {
// 引數個數不滿足的處理
var f2 = function f2() {
var args2 = Array.prototype.slice.call(arguments, 0);
return f1.apply(null, args.concat(args2));
}
f2.toString = function() {
return inspectFn(fx) + inspectArgs(args);
}
return f2;
}
};
}
複製程式碼
其中 f2.toString
的實現是會報錯的,我已經向作者提交了PR,這段無關緊要,可以跳過不看這個 fs.toString
的實現。很顯然實現curry函式的核心就是判斷引數個數,然後各種使用apply函式。
接下來就可以體驗curry的好處:
add = curry(function(x, y) {
return x + y;
});
const add5 = add(5);
ad5(4)
// 9
複製程式碼
這只是一個非常小的例子,原始碼還有很多例子:
add = curry(function(x, y) {
return x + y;
});
match = curry(function(what, x) {
return x.match(what);
});
replace = curry(function(what, replacement, x) {
return x.replace(what, replacement);
});
filter = curry(function(f, xs) {
return xs.filter(f);
});
map = curry(function map(f, xs) {
return xs.map(f);
});
reduce = curry(function(f, a, xs) {
return xs.reduce(f, a);
});
split = curry(function(what, x) {
return x.split(what);
});
join = curry(function(what, x) {
return x.join(what);
});
複製程式碼
在這裡我們可以看到,所有的資料引數都作為了最後一個引數,很明顯這樣在使用時的好處就在於,這可以成為一種預載入函式函式。
非常明顯的在於這樣柯里化處理函式,可以讓這些函式成為底層部署的函式。