ホームページ >ウェブフロントエンド >jsチュートリアル >javascript_javascriptスキルのカリー化機能の紹介

javascript_javascriptスキルのカリー化機能の紹介

WBOY
WBOYオリジナル
2016-05-16 17:56:151488ブラウズ

初期のカリー関数は少し多態性がありました。つまり、分岐は関数パラメーターに基づいて内部的に選択されました。

コードをコピー コードは次のとおりです。以下の通り:

//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;
}




[Ctrl A すべて選択 注: 外部 Js を導入する必要がある場合は、 を実行するために更新する必要があります]
その後クロージャの人気、そして配列変換引数の技術の発見により、現代のカリー化関数がついに登場しました。ちょうど 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 回目の実行で最終的に完了します。ただし、このパラメータに関するいくつかの記事はまだ作成できます。次の関数を見てください:



コードをコピー
コードは次のとおりです。 function sum( ){ var result=0;
for(var i=0, n=arguments.length; iresult = argument[i];
return result;
}
alert(sum(1,2,3,4,5)); // 15


であれば、いわゆるパラメータ不足の問題はありません。パラメータを渡すと、計算も行われます。しかし、パラメーターが渡されない場合はどうなるでしょうか?そうですね、パラメータがあるかないかの違いです。パラメーターが存在する場合は、それ自体を継続的に実行させることができます。最後に、パラメーターなしで 1 回実行されます。つまり、前の手順はパラメータを保存するために使用されます。



コードをコピーします
コードは次のとおりです。 var sum2=カレー(合計); 🎜>sum2 = sum2(1)(2)(3)(4)(5); sum2(); // 15

一般的なカリー化関数と比較すると、これは少し難しいです。詳細についてはコメントを参照してください:



コードをコピーします

コードは次のとおりです:

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([]);
}


[Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。