2015-05-22 8 views
6

Così ho la seguente funzione:Perché un ritorno non è definito ma console.log restituisce un int?

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

} 

Esso viene chiamato con:

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

e dà questo:

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 

come output. Quello di cui sono confuso è perché acc darebbe il valore corretto per console.log ma sarebbe "indefinito" in base a ciò che viene restituito.

risposta

6

Questo è un buon compromesso. La ricorsione può far girare la testa. Il motivo per cui non è definito è perché non tutte le iterazioni restituiscono un valore, e per quelle che non vengono definite indefinite - lo stesso come se si impostasse una variabile su qualsiasi funzione che non restituisce un valore.

Si confonde però con la ricorsione, perché il valore di ritorno che si sta vedendo in questo caso è dalla prima chiamata e dall'ultima iterazione completata. A differenza di una normale chiamata di metodo in cui return interrompe l'esecuzione del metodo - rimandandolo da dovunque sia arrivato, la ricorsione ha ancora la sua strada attraverso lo stack delle chiamate, restituendo tutti i valori che deve restituire, incluso undefined, nel retro ordine in cui sono stati chiamati. Quindi in realtà sta dando alla tua console.log call quattro valori di ritorno: 15, indefiniti, indefiniti, indefiniti.

Poiché sincrono, console.log non può essere eseguito fino a quando non viene eseguito il metodo chiamato. Ciò che emette è l'ultimo valore che ottiene, o indefinito. Se si attiva un ritorno dopo la chiamata al metodo nel blocco else, vedrai che ottieni 5 o il valore di acc dopo la prima iterazione della funzione.

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

nel blocco altro, dovrebbe essere return multiplyT(a, b, acc);

5

È necessario tornare dal blocco altro pure.

Nel tuo caso, anche se il valore di acc viene aggiornato tale valore viene restituito quando mot 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

che stai chiamando ricorsivamente la funzione multiplyT, ma non sta controllando il ritorno. Quindi, multiplyT (5,3,0) non restituisce un valore nella prima chiamata e la funzione restituisce undefined.

È vero che lo stack è in esecuzione, ma la prima chiamata è la più importante: è necessario ottenere il valore dalla funzione interna ricorsiva che ha restituito il valore finale.

correggere il codice nel ramo altro in modo da poter restituire la chiamata ricorsiva:

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

mi è venuta in mente una buona soluzione a questo mentre si lavora su uno dei miei progetti in cui ho Traverse un oggetto JSON complesso di restituire alcuni dati sulla ricerca per l'id.

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

Qui, eseguiamo un ciclo while per vedere se la chiamata di funzione ricorsiva restituisce un valore vero o indefinito.Se restituisce qualcosa di diverso da undefined, restituirà i dati.

Problemi correlati