2015-05-22 4 views
6

So habe ich die folgende Funktion: DieseWarum sollte eine Rückgabe nicht definiert sein, aber console.log gibt ein int zurück?

console.log(multiplyT(5,3,0)); 

Und gibt:

var multiplyT = function(a, b, acc) { 

    if (b == 0) { 
     console.log("BASE CASE: ", acc); 

     return acc; 
    } else { 
     b--; 
     acc = acc + a; 
     console.log("NOT THE BASE CASE: ", a,b,acc); 
     multiplyT(a, b, acc); 
    } 

} 

Es mit aufgerufen wird

NOT THE BASE CASE: 5 2 5 
NOT THE BASE CASE: 5 1 10 
NOT THE BASE CASE: 5 0 15 
BASE CASE: 15 
undefined 

als Ausgabe. Was mich verwirrt ist, warum acc den richtigen Wert für die console.log geben würde, aber "undefiniert" sein sollte, je nachdem, was zurückgegeben wird.

Antwort

6

Dies ist ein guter. Rekursion kann deinen Kopf zum Drehen bringen. Der Grund ist, dass es nicht definiert ist, weil nicht alle Iterationen einen Wert zurückgeben, und für diejenigen, die nicht undefiniert sind - genau wie wenn Sie eine Variable auf eine Funktion setzen, die keinen Wert zurückgibt.

Es wird jedoch mit Rekursion verwirrend, weil der Rückgabewert, den Sie in diesem Fall sehen, von der zuerst aufgerufenen und zuletzt abgeschlossenen Iteration stammt. Im Gegensatz zu einem normalen Methodenaufruf, bei dem die Ausführung der Methode abgebrochen wird und sie von wo auch immer zurückgegeben wird, hat die Rekursion immer noch ihren Weg durch den Aufrufstapel zurück und gibt alle Werte zurück, die zurückgegeben werden müssen, einschließlich undefiniert, im umgekehrten Fall Reihenfolge, in der sie angerufen wurden. Es gibt also Ihren console.log Aufruf vier Rückgabewerte: 15, undefined, undefined, undefined.

Da es synchron ist, kann console.log erst ausgeführt werden, wenn die aufgerufene Methode ausgeführt wird. Was es ausgibt, ist der letzte Wert, den es bekommt, oder undefiniert. Wenn Sie nach dem Methodenaufruf in Ihrem else-Block eine Rückgabe eingeben, erhalten Sie 5 oder den Wert von acc nach der ersten Iteration der Funktion.

var multiplyT = function(a, b, acc) { 

    if (b == 0) { 
    console.log("BASE CASE: ", acc); 

    return acc; 
    } else { 
    b--; 
    acc = acc + a; 
    console.log("NOT THE BASE CASE: ", a,b,acc); 
    multiplyT(a, b, acc); 
    return acc; 
    } 
} 
console.log(multiplyT(5,3,0)); 
9

In Ihrem anderen Block, sollte es return multiplyT(a, b, acc);

5

Sie müssen auch von dem anderen Block zurückkehren.

In Ihrem Fall, obwohl der Wert von acc aktualisiert wird dieser Wert mot zurückgegeben, wenn b != 0

var multiplyT = function(a, b, acc) { 
 

 
    if (b == 0) { 
 
    console.log("BASE CASE: ", acc); 
 

 
    return acc; 
 
    } else { 
 
    b--; 
 
    acc = acc + a; 
 
    console.log("NOT THE BASE CASE: ", a, b, acc); 
 
    return multiplyT(a, b, acc); //return here 
 
    } 
 

 
} 
 

 
console.log(multiplyT(5, 3, 0));

1

Sie rekursiv die multiplyT Funktion aufrufen, aber Sie sind nicht steuern die Rückkehr. Dann gibt multiplyT (5, 3, 0) im ersten Aufruf keinen Wert zurück, und die Funktion gibt dann undefined zurück.

Es ist wahr, dass der Stapel ausgeführt wird, aber der erste Aufruf ist wichtiger: Er muss den Wert aus der rekursiven inneren Funktion abrufen, die den endgültigen Wert zurückgegeben hat.

Befestigen Sie den Code in den anderen Zweig, so dass Sie den rekursiven Aufruf zurückkehren können:

var multiplyT = function(a, b, acc) { 

    if (b == 0) { 
     console.log("BASE CASE: ", acc); 

     return acc; 
    } else { 
     b--; 
     acc = acc + a; 
     console.log("NOT THE BASE CASE: ", a,b,acc); 
     return multiplyT(a, b, acc); 
    } 
} 
0

Ich habe mit einer guten Lösung für dieses, während kommen der Arbeit an einem meiner Projekte, in denen ich ein komplexes JSON-Objekt durchqueren auf der Suche nach der id einige Daten zurückzukehren.

Hier führen wir eine while-Schleife aus, um festzustellen, ob der rekursive Funktionsaufruf einen wahren Wert oder undefiniert zurückgibt.Wenn etwas anderes als undefined zurückgegeben wird, werden die Daten zurückgegeben.

Verwandte Themen