初期のカリー関数は少し多態性がありました。つまり、分岐は関数パラメーターに基づいて内部的に選択されました。
//http://www.openlaszlo.org/pipermail/laszlo-user/2005-March/000350.html
// ★★2005 年 3 月 8 日、 00:06、Steve Albin は次のように書きました:
function add(a, b) {
if (arguments.length < 1) {
return add
} else if (arguments.length < 2) {
return function(c) { return a c }
} else {
return a b;
}
}
var myadd = add( 2 ); 🎜>var total = myadd(3);
日本の先駆者は、引数を理解する前に、非常に複雑な正規表現と eval を使用して、eval に似たメソッドを考え出した可能性があります。 Array のネイティブ メソッドを使用して配列に変換することもできます。
functioncurrency(fun) {
if (typeof fun != 'function') {
throw new Error("引数は関数である必要があります。")
}
if (fun.arity == 0) {
throw new Error( "関数には複数の引数が必要です。");
}
var funText = fun.toString()
var args = /function .*((.*) )(. *)/.exec(funText)[1].split(', ');
var firstArg = args.shift();
varrestArgs = args.join(', '); 🎜>var body = funText.replace(/function .*(.*) /, "");
var curriedText =
"function (" firstArg ") {"
"return function ("restArgs")"body
"}";
eval("var curried =" curriedText);
return curried;
}
その後クロージャの人気、そして配列変換引数の技術の発見により、現代のカリー化関数がついに登場しました。ちょうど 15 世紀から 17 世紀の大航海時代の地理的発見と同じように、JavaScript の世界が突然開かれました。たくさん。
//シンプルでモダンなカリー化関数
関数カレー (fn, スコープ) {
var スコープ = スコープ ||
var args = [];
for (var i=2, len = argument.length; i args.push(arguments[i]);
return function() {
fn.apply(scope, args);
一般的なカリー化関数には 2 つの関数しかありません。実行状況は次のようになります。1 回目の実行ではパラメータが不足しており、内部関数に戻り、2 回目の実行で最終的に完了します。ただし、このパラメータに関するいくつかの記事はまだ作成できます。次の関数を見てください:
コードをコピー
for(var i=0, n=arguments.length; i
result = argument[i];
return result;
}
alert(sum(1,2,3,4,5)); // 15
であれば、いわゆるパラメータ不足の問題はありません。パラメータを渡すと、計算も行われます。しかし、パラメーターが渡されない場合はどうなるでしょうか?そうですね、パラメータがあるかないかの違いです。パラメーターが存在する場合は、それ自体を継続的に実行させることができます。最後に、パラメーターなしで 1 回実行されます。つまり、前の手順はパラメータを保存するために使用されます。
コードをコピーします
一般的なカリー化関数と比較すると、これは少し難しいです。詳細についてはコメントを参照してください:
コードをコピーします
コードは次のとおりです:
var curry= function(fn){//原函数的参数为函数
return function(args){//内部函数的参数为数组,由于立即执行,因此直接到第三重去
//args是相对于第三重内部函数可是全局变量
var self= arguments.callee;//把自身保存起来(就是那个数组为参数的第二重函数)
return function(){ //这才是第二次调用的函数
if(arguments.length){//如果还有要添加的参数
[].push.apply(args,arguments);//apply把当前传入的所有参数放进args中
return self(args);
}else{
return fn.apply(this,args);//apply的第二参数为数组
}
}
}([]);
};
function sum(){
var result=0;
for(var i=0, n=arguments.length; iresult += arguments[i];
}
return result;
};
var curry = function(fn){//原函数的参数为函数
return function(args){//内部函数的参数为数组,由于立即执行,因此直接到第三重去
var self= arguments.callee;//把自身保存起来
return function(){ //这才是第二次调用的函数
if(arguments.length){//如果还有要添加的参数
[].push.apply(args,arguments);
return self(args);
}
else return fn.apply(this,args);//执行
}
}([]);
};
var sum2= curry(sum);
sum2= sum2(1)(2)(3)(4)(5);
alert(sum2());
或者每次传入多个参数:
function sum(){
var result=0;
for(var i=0, n=arguments.length; iresult += arguments[i];
}
return result;
};
var curry = function(fn){//原函数的参数为函数
return function(args){//内部函数的参数为数组,由于立即执行,因此直接到第三重去
var self= arguments.callee;//把自身保存起来
return function(){ //这才是第二次调用的函数
if(arguments.length){//如果还有要添加的参数
[].push.apply(args,arguments);
return self(args);
}
else return fn.apply(this,args);//执行
}
}([]);
};
var sum2= curry(sum);
sum2= sum2(1,2,3);
sum2= sum2(4,5,6);
sum2= sum2(7,8,9);
alert(sum2());
但上面的函数有不足之处,最后怎么也要放个括号,我们想只要参数足够就返回结果,多出的参数忽略。改进如下:
function curry(f) {
if (f.length == 0) return f;
function iterate(args) {
if (args.length <= f.length)
return f.apply(null, args);
return function () {
return iterate(args.concat(Array.prototype.slice.call(arguments)));
};
}
return iterate([]);
}