Ich kann eine rekursive Funktion in einer Variablen wie folgt erstellen:
/* Count down to 0 recursively.
*/
var functionHolder = function (counter) {
output(counter);
if (counter > 0) {
functionHolder(counter-1);
}
}
Damit functionHolder(3);
würde ausgegeben 3
2
1
0
. Angenommen, ich habe Folgendes getan:
var copyFunction = functionHolder;
copyFunction(3);
würde 3
2
1
0
wie oben ausgeben . Wenn ich mich dann functionHolder
wie folgt geändert habe :
functionHolder = function(whatever) {
output("Stop counting!");
Dann functionHolder(3);
würde Stop counting!
wie erwartet geben.
copyFunction(3);
Jetzt gibt es, 3
Stop counting!
wie es sich bezieht functionHolder
, nicht die Funktion (auf die es selbst zeigt). Dies könnte unter bestimmten Umständen wünschenswert sein, aber gibt es eine Möglichkeit, die Funktion so zu schreiben, dass sie sich selbst aufruft und nicht die Variable, die sie enthält?
Das heißt, ist es möglich, nur die Leitung functionHolder(counter-1);
so zu ändern , dass das Durchlaufen all dieser Schritte immer noch ergibt, 3
2
1
0
wenn wir anrufen copyFunction(3);
? Ich habe es versucht, this(counter-1);
aber das gibt mir den Fehler this is not a function
.
quelle
Antworten:
Verwenden benannter Funktionsausdrücke:
Sie können einem Funktionsausdruck einen Namen geben, der tatsächlich privat ist und nur innerhalb der Funktion sichtbar ist, wenn Sie selbst:
Hier
myself
ist nur innerhalb der Funktion selbst sichtbar .Mit diesem privaten Namen können Sie die Funktion rekursiv aufrufen.
Siehe
13. Function Definition
ECMAScript 5-Spezifikation:Bitte beachten Sie, dass sich Internet Explorer bis Version 8 nicht korrekt verhält, da der Name tatsächlich in der umgebenden Variablenumgebung sichtbar ist und auf ein Duplikat der eigentlichen Funktion verweist (siehe den Kommentar von Patrick Dw unten).
Argumente verwenden.callee:
Alternativ können Sie
arguments.callee
auf die aktuelle Funktion verweisen:Die 5. Ausgabe von ECMAScript verbietet jedoch die Verwendung von Argumenten.callee () im strengen Modus :
quelle
myself
ist , ist es tatsächlich in der umgebenden Variablenumgebung sichtbar und verweist auf ein Duplikat der eigentlichenmyself
Funktion. Sie sollten jedoch in der Lage sein, die äußere Referenznull
festzulegen.return n * myself(n-1);
?Sie können mit
arguments.callee
[MDN] auf die Funktion selbst zugreifen :Dies wird jedoch im strengen Modus unterbrochen.
quelle
TypeError
, aber ich habe nichts gefunden, was offiziell besagt, dassarguments.callee
(oder eine Verletzung des strengen Modus ) außerhalb des "strengen Modus" veraltet ist.Sie können den Y-Kombinator verwenden: ( Wikipedia )
Und Sie können es so verwenden:
quelle
Ich weiß, dass dies eine alte Frage ist, aber ich dachte, ich würde eine weitere Lösung vorstellen, die verwendet werden könnte, wenn Sie die Verwendung benannter Funktionsausdrücke vermeiden möchten. (Nicht sagen, dass Sie sie vermeiden sollten oder nicht, sondern nur eine andere Lösung präsentieren)
quelle
Hier ist ein sehr einfaches Beispiel:
Beachten Sie, dass die
counter
Anzahl "rückwärts" in Bezug aufslug
den Wert zählt. Dies liegt an der Position, an der wir diese Werte protokollieren, da die Funktion vor der Protokollierung wiederholt wird. Daher verschachteln wir uns im Wesentlichen immer tiefer im Aufrufstapel, bevor die Protokollierung stattfindet.Sobald die Rekursion das letzte Call-Stack-Element erreicht, trampoliert sie "out" aus den Funktionsaufrufen, während das erste Inkrement von
counter
innerhalb des letzten verschachtelten Aufrufs auftritt.Ich weiß, dass dies keine "Korrektur" des Codes des Fragestellers ist, aber angesichts des Titels dachte ich, ich würde Rekursion generisch veranschaulichen , um die Rekursion direkt besser zu verstehen.
quelle