Heim > Web-Frontend > js-Tutorial > Detaillierte Erläuterung des JavaScript-Funktions-Curryings

Detaillierte Erläuterung des JavaScript-Funktions-Curryings

黄舟
Freigeben: 2017-02-27 14:29:14
Original
1561 Leute haben es durchsucht

Detaillierte Erklärung des JavaScript-Funktions-Curryings

Baidu Encyclopedias Erklärung des Curryings: In der Informatik ist Currying der Prozess des Akzeptierens einer Technik, die eine Funktion mit umwandelt mehrere Parameter in eine Funktion umwandeln, die einen einzelnen Parameter akzeptiert (den ersten Parameter der ursprünglichen Funktion) und eine neue Funktion zurückgibt, die die übrigen Parameter akzeptiert und ein Ergebnis zurückgibt. Diese Technik wurde von Christopher Strachey nach dem Logiker Haskell Curry benannt, obwohl sie von Moses Schönfinkel und Gottlob Frege erfunden wurde.
Ich glaube, dass nicht viele Menschen sofort verstehen können, welche Funktion Curry hat, nachdem sie die obige Erklärung gelesen haben. Laienhaft ausgedrückt besteht der Hauptzweck des Funktions-Currying darin, Funktionsparameter zu reduzieren und einige feste Parameter zu privatisieren. Das Folgende zeigt einen sehr einfachen Code zur Berechnung der Fläche eines Kreises, um das Prinzip des Funktionscurryings zu veranschaulichen:

//circle函数,接受半径r和πfunction circle(r,p){
    //计算半径为r的圆的面积
    var area=p*r*r;    return area;
}/*
 * 通过函数柯里化来简化circle函数,只传入半径就能计算出面积
 * 不管怎么样,π是不会变的,因此我们将他写死,不需要外部调用传入
 */function curryCircle(r){
    var p=3.14;    var area=p*r*r;    return area;
}
Nach dem Login kopieren
Nach dem Login kopieren

Vielleicht denken Sie, dass dieser Code seltsam ist, aber das ist das wahre Gesicht der Funktion Curry. Natürlich ist der obige Code nur ein sehr kleines Beispiel. Das Currying von Funktionen in der realen Welt wird etwas bösartiger sein. Unter der Annahme, dass π nicht eindeutig ist (wir haben beispielsweise drei Arten von π), ändert sich π in unserer Formel zur Berechnung der Kreisfläche je nach Szenario. Zu diesem Zeitpunkt können wir es nicht direkt aufschreiben, sondern müssen π konfigurieren je nach Umgebung:

//circle函数,接受半径r和π
function circle(r,p){
    //计算半径为r的圆的面积
    var area=p*r*r;    
    return area;
}
//针对circle函数的柯里化函数function curry(fn,p){
    var finalMethod=function(r){
        var result=fn(r,p);        return result;
    }    return finalMethod;
}
//我们有3种不同的πvar curryCircle1=curry(circle,1.14);
var curryCircle2=curry(circle,2.14);
var curryCircle3=curry(circle,3.14);
//输出:4.56  8.56  12.56
console.log(curryCircle1(2),curryCircle2(2),curryCircle3(2));
Nach dem Login kopieren

Wie Sie sehen können, kapselt die Curry-Methode die grundlegendste Kreismethode, speichert den eingestellten p-Parameter (π) und gibt eine finalMethod-Methode zurück, sodass wir sie schließlich aufrufen Bei der finalen Methode müssen wir nur den Parameter r (Radius) übergeben, um ihn abzuschließen. Mit Hilfe des Funktionscurryings stehen uns drei vereinfachte Methoden zur Berechnung der Fläche eines Kreises zur Verfügung. Die oben gezeigte Currying-Funktion kann nur auf die Berechnung der Kreisfläche angewendet werden. Diesmal schreiben wir eine allgemeinere Currying-Funktion:

function curry(fn){
    //第一个参数是基础执行方法,slice切除
    var args=Array.prototype.slice.call(arguments,1);    //直接返回匿名函数
    return function(){
        //slice新参数以便能调用concat
        var innerArgs=Array.prototype.slice.call(arguments);        //将配置的参数和新传入的参数合并
        var finalArgs=args.concat(innerArgs);        return fn.apply(null,finalArgs);
    };
}
Nach dem Login kopieren
Nach dem Login kopieren

Die Hauptaufgabe der Curry()-Funktion besteht darin, die Funktion zurückzugeben Parameter sind sortiert. Der erste Parameter von Curry () ist die zu curryende Funktion, und die anderen Parameter sind die zu übergebenden Werte. Um alle Parameter nach dem ersten Parameter zu erhalten, wird die Methode „slice()“ für das Argumentobjekt aufgerufen und Parameter 1 übergeben, um anzugeben, dass das zurückgegebene Array alle Parameter ab dem zweiten Parameter enthält. Das args-Array enthält dann die Argumente der externen Funktion. In der inneren Funktion wird das Array innerArgs erstellt, um alle übergebenen Parameter zu speichern (slice() wird erneut verwendet). Sobald Sie über die Parameterarrays verfügen, in denen die externen und internen Funktionen gespeichert sind, können Sie sie mit der Methode concat() in finalArgs zusammenführen. Verwenden Sie abschließend apply(), um das Ergebnis an die Funktion zu übergeben. Dadurch wird eine allgemeine Curry-Funktion erreicht. Wenn Sie an dieser Stelle noch etwas Energie haben, können Sie weiterlesen. Wir werden die in jQuery verwendete Funktion Currying vorstellen.
Beim Currying einer Methode müssen wir nicht einmal fn übergeben, um Currying anzuweisen, unsere Funktion zu umschließen. Wir können die Funktion und das Currying direkt über den Prototyp binden:

Function.prototype.curry=function(){
    //利用原型的便利,我们可以直接通过this引用到方法
    var fn=this;    var args=Array.prototype.slice.call(arguments);    return function(){
        var arg=0;        //循环校验先前传入的参数和新传入的参数是否有差别
        for(var i=0;i<args.length && arg<arguments.length;i++){            if(args[i]===undefined){
                args[i]=arguments[arg++];
            }
        }        return fn.apply(this,args);
    };
};
Nach dem Login kopieren
Nach dem Login kopieren

Anders als zuvor , wir erhalten die Methodenreferenz über diese Referenz. Wenn wir also eine Funktion curryen müssen, müssen wir nur so schreiben:

var delay=setTimeout.curry(undefined,10);
Nach dem Login kopieren
Nach dem Login kopieren

delay ist eine Funktion, die curried wurde. Die setTimeout-Funktion setzt eine 10 Millisekunden Verzögerung im Voraus. Wir verwenden immer noch args, um die Parameterkonfiguration zu speichern, aber dieses Mal gibt es einen Unterschied: Der Unterschied zwischen args und arguments wird innerhalb der for-Schleife überprüft, und basierend auf dieser Beurteilung wird das Parameterspleißen abgeschlossen. Daher müssen die an Curry übergebenen Parameter vollständige Parameter sein (was bedeutet, dass undefinierte Werte übergeben werden müssen). Schließlich haben wir eine Currying-Methode implementiert, die keine Übergabe von fn erfordert.

Ausführliche Erklärung des JavaScript-Funktions-Curryings

Baidu Encyclopedias Erklärung des Curryings: In der Informatik bedeutet Currying, eine Funktion, die mehrere Parameter akzeptiert, in eine Funktion umzuwandeln, die einen akzeptiert. Eine Technik, die eine Funktion mit übernimmt einen einzelnen Parameter (den ersten Parameter der ursprünglichen Funktion) und gibt eine neue Funktion zurück, die die übrigen Parameter akzeptiert und ein Ergebnis zurückgibt. Diese Technik wurde von Christopher Strachey nach dem Logiker Haskell Curry benannt, obwohl sie von Moses Schönfinkel und Gottlob Frege erfunden wurde.
Ich glaube, dass nicht viele Menschen sofort verstehen können, welche Funktion Curry hat, nachdem sie die obige Erklärung gelesen haben. Laienhaft ausgedrückt besteht der Hauptzweck des Funktions-Currying darin, Funktionsparameter zu reduzieren und einige feste Parameter zu privatisieren. Das Folgende zeigt einen sehr einfachen Code zur Berechnung der Fläche eines Kreises, um das Prinzip des Funktionscurryings zu veranschaulichen:

//circle函数,接受半径r和πfunction circle(r,p){
    //计算半径为r的圆的面积
    var area=p*r*r;    return area;
}/*
 * 通过函数柯里化来简化circle函数,只传入半径就能计算出面积
 * 不管怎么样,π是不会变的,因此我们将他写死,不需要外部调用传入
 */function curryCircle(r){
    var p=3.14;    var area=p*r*r;    return area;
}
Nach dem Login kopieren
Nach dem Login kopieren

Vielleicht denken Sie, dass dieser Code seltsam ist, aber das ist das wahre Gesicht der Funktion Curry. Natürlich ist der obige Code nur ein sehr kleines Beispiel. Das Currying von Funktionen in der realen Welt wird etwas bösartiger sein. Unter der Annahme, dass π nicht eindeutig ist (wir haben beispielsweise drei Arten von π), ändert sich π in unserer Formel zur Berechnung der Kreisfläche je nach Szenario. Zu diesem Zeitpunkt können wir es nicht direkt aufschreiben, sondern müssen π konfigurieren je nach Umgebung:

//circle函数,接受半径r和πfunction circle(r,p){
    //计算半径为r的圆的面积
    var area=p*r*r;    return area;
}//针对circle函数的柯里化函数function curry(fn,p){
    var finalMethod=function(r){
        var result=fn(r,p);        return result;
    }    return finalMethod;
}
//我们有3种不同的π
var curryCircle1=curry(circle,1.14);
var curryCircle2=curry(circle,2.14);
var curryCircle3=curry(circle,3.14);
//输出:4.56  8.56  12.56
console.log(curryCircle1(2),curryCircle2(2),curryCircle3(2));
Nach dem Login kopieren

可以看到,curry方法通过封装最基础的circle方法,同时保存设置好的p参数(π),并返回一个finalMethod方法,这样我们最终调用finalMethod时就只需要传入参数r(半径)就可以完成。借助函数柯里化,我们拥有了三个简化的计算圆面积方法。上面展示的函数柯里化只能适用于圆面积的计算,这次我们编写一个更通用的柯里化函数:

function curry(fn){
    //第一个参数是基础执行方法,slice切除
    var args=Array.prototype.slice.call(arguments,1);    //直接返回匿名函数
    return function(){
        //slice新参数以便能调用concat
        var innerArgs=Array.prototype.slice.call(arguments);        //将配置的参数和新传入的参数合并
        var finalArgs=args.concat(innerArgs);        return fn.apply(null,finalArgs);
    };
}
Nach dem Login kopieren
Nach dem Login kopieren

curry()函数的主要工作就是将被返回函数的参数进行排序。Curry()的第一个参数是要进行柯里化的函数,其他参数是要传入的值。为了获取第一个参数之后的所有参数,在arguments对象上调用了slice()方法,并传入参数1表示被返回的数组包含从第二个参数开始的所有参数。然后args数组包含了来自外部函数的参数。在内部函数中,创建了innerArgs数组用来存放所有传入的参数(又一次使用了slice())。有了存放来自外部函数和内部函数的参数数组后,就可以使用concat()方法将他们合并成finalArgs。最后使用apply()将结果传递给该函数。这样就实现了一个通用的函数柯里化。如果到这此还有余力的读者可以接着往下看,我们将要介绍jQuery中使用的函数柯里化。
在针对某个方法进行柯里化时,我们甚至不用传入fn来告诉柯里化来包装我们的函数,我们可以通过原型直接将函数和柯里化绑定:

Function.prototype.curry=function(){
    //利用原型的便利,我们可以直接通过this引用到方法
    var fn=this;    var args=Array.prototype.slice.call(arguments);    return function(){
        var arg=0;        //循环校验先前传入的参数和新传入的参数是否有差别
        for(var i=0;i<args.length && arg<arguments.length;i++){            if(args[i]===undefined){
                args[i]=arguments[arg++];
            }
        }        return fn.apply(this,args);
    };
};
Nach dem Login kopieren
Nach dem Login kopieren

与之前不同,我们通过this引用获取了方法引用,这样当我们需要将某个函数柯里化时,只要这样写就可以:

var delay=setTimeout.curry(undefined,10);
Nach dem Login kopieren
Nach dem Login kopieren

delay就是一个已经被提前设定了10毫秒延迟的setTimeout函数。我们仍然通过args来保存参数配置,不过这次有点区别:在for循环内部会校验args和arguments的区别,以此判断来完成参数拼接。所以传给curry的参数必须是完整参数(即意味着不传的值要传入undefined)。最终我们实现了一个不需要传入fn的柯里化方法。

 以上就是详解JavaScript函数柯里化 的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage