Vor kurzem lerne ich funktionale JavaScript-Programmierung und interessiere mich sehr für die berühmte Curry-Funktion. Nennen wir sie vorerst die Originalfunktion und gibt a zurück Funktion, Curry. Funktion, die zurückgegebene Curry-Funktion ist während des Ausführungsprozesses kontinuierlich eine Funktion, die die übergebenen Parameter speichert, bis die Bedingungen für die Ausführung der ursprünglichen Funktion ausgelöst werden. Dies ist allgemeiner, daher geben wir zur Veranschaulichung ein Beispiel:
Ursprüngliche Funktion:
var add = (x, y) => x + y
Curry-Funktion:
var curryAdd = curry(add)
Dieses Add-In erfordert zwei Parameter, aber Unsere CurryAdd-Ausführung kann weniger Parameter übergeben als die von Add benötigten Parameter. CurryAdd schreibt diesen Parameter nicht auf und gibt einen anderen zurück Die eingehenden Parameter werden über eine Variable zum Aufzeichnen der eingehenden Parameter verfügen, die der Gesamtzahl der durch Hinzufügen erforderlichen Parameter entspricht Ergebnis.
// 此时只传入了一个参数 根据判断返回的是一个函数 var add2 = curryAdd(2) // add2 = function(...) {}
// 此时累计传入了两个参数 等于了add需要参数的总和 所以返回的是一个结果 // 相当于执行了add(2)(3) var result = add2(3) // result = 5
Es ist ziemlich gut, oder? Nun, unser Ziel ist es, diese magische Curry-Funktion zu schreiben, und wir müssen sie in einer Zeile schreiben. Machen Sie sich keine Sorgen, lassen Sie uns analysieren, wie man schreibt es zuerst und optimieren Sie es dann Schritt für Schritt.
Schauen wir uns gemäß der obigen Beschreibung an, was die Curry-Funktion benötigt. Zuerst benötigen wir eine Variable, um die Anzahl der Parameter der ursprünglichen Funktion zu speichern. Wir wissen, dass die Funktion ein Attribut namens Länge hat. und das ist es. Wir verwenden limit, um es zu speichern.
var curry = function(fn) { var limit = fn.length ... }
Die Curry-Funktion sollte eine Funktion zurückgeben, und diese Funktion muss ausgeführt werden. Die Frage ist, ob die Ausführung dieser Funktion aktiviert wird die Ausführung der ursprünglichen Funktion. Das Problem tritt oberhalb der übergebenen Parameter auf. Rückgabefunktion oder Ergebnis? Dies ist in der Tat ein Problem. Schreiben wir zuerst das Rückgabeergebnis. Wenn die übergebenen Parameter mit den von der ursprünglichen Funktion erforderlichen Parametern übereinstimmen, führen wir die ursprüngliche Funktion fn
var curry = function(fn) { var limit = fn.length return function (...args) { if (args.length >= limit) { return fn.apply(null, args) } } }
aus Speicherung Hier gibt es zwei Punkte für die Funktion von Parametern: Der eine ist, dass wir den Verlauf der übergebenen Parameter aufzeichnen müssen. Der andere ist, was die zurückgegebene Funktion tun muss. Wir müssen nur die Funktion zurückgeben. Die Akkumulation der ausgeführten Parameter erfüllt den Zweck der Aufzeichnung der übergebenen Parameter. Daher haben wir an concat zu args.concat (args2) gedacht und so weiter. Die von uns zurückgegebene Funktion muss wiederholt werden Die oben genannten Dinge, also die Parameter, sind: Die Funktion von args muss etwas tun, also braucht sie einen Namen, sonst können wir sie nicht ausführen, wir nennen sie JudgeCurry
var curry = function(fn) { var limit = fn.length return function (...args) { if (args.length >= limit) { return fn.apply(null, args) } else { return function(...args2) { } } } }
Wir haben diese magische Curry-Funktion endlich fertig geschrieben. In Kombination mit Compose ist sie wirklich cool.
var curry = function(fn) { var limit = fn.length return function judgeCurry (...args) { if (args.length >= limit) { return fn.apply(null, args) } else { return function(...args2) { return judgeCurry.apply(null, args.concat(args2)) } } } }
Okay, mal sehen, was falsch ist. Übrigens müssen wir einen Wert zuweisen, um den Grenzwertparameter nicht zu verwenden Wenn Sie es verwenden, kann die Zuweisung nicht in einer Zeile erfolgen.
var currySingle = fn => judgeCurry = (...args) => args.length >= fn.length ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2))
Wenn Sie die Parameter beurteilen müssen, wird fn.length ständig ausgewertet ist sicher, wir wollen es nicht jedes Mal bewerten, aber was soll ich tun, wenn ich Limit nicht verwenden möchte? Sie haben bestimmt daran gedacht, die Funktion sofort auszuführen! !
var currySingle = fn => { var limit = fn.length var judgeCurry = null return judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2)) }
Ich muss über die Magie von Javascript seufzen. Schließlich haben wir dieses magische Curry in einer Zeile geschrieben.
var currySingle = fn => ((limit) => judgeCurry = (...args) => args.length >= limit ? fn.apply(null, args) : (...args2) => judgeCurry.apply(null, args.concat(args2)))(fn.length)