2015-05-22 18 views
6

Więc mam następującą funkcję:Dlaczego powrót byłby niezdefiniowany, ale console.log zwrócił 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); 
    } 

} 

To jest wywoływana z:

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

i daje to:

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 

jako wyjście. To co mnie martwi to to, dlaczego acc dałoby poprawną wartość dla console.log, ale byłoby "niezdefiniowane" zgodnie z tym, co jest zwracane.

Odpowiedz

6

To jest dobry. Rekursja może sprawić, że twoja głowa się zakręci. Powodem, dla którego jest niezdefiniowany, jest to, że nie wszystkie iteracje zwracają wartość, a dla tych, które nie są niezdefiniowane - to tak samo, jak w przypadku ustawienia zmiennej na dowolną funkcję, która nie zwraca wartości.

Jest to mylące z rekurencją, ponieważ wartość zwracana w tym przypadku pochodzi z pierwszej i ostatniej zakończonej iteracji. W przeciwieństwie do zwykłego wywołania metody, w której powrót powoduje przerwanie wykonywania metody - odesłanie jej z powrotem do miejsca, z którego przybył, rekursja nadal ma powracający powrót do stosu wywołań, zwracając wszelkie wartości, które ma oddawać, w tym niezdefiniowane, w odwrotnej kolejności. porządek, w którym zostali wezwani. Tak więc w rzeczywistości wywołuje on cztery wartości zwracane przez console.log: 15, undefined, undefined, undefined.

Ponieważ jest to synchroniczne, console.log nie może zostać wykonane, dopóki nie zostanie wywołana wywołana metoda. To, co przekazuje, jest ostatnią wartością, którą otrzymuje, lub nieokreśloną. Jeśli wrócisz po wywołaniu metody w swoim bloku else, zobaczysz, że otrzymujesz 5 lub wartość acc po pierwszej iteracji funkcji.

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

W swojej innego bloku, należy return multiplyT(a, b, acc);

5

Musisz wrócić z innego bloku, jak również.

W twoim przypadku, mimo że wartość acc jest aktualizowana że wartość jest zwracana, gdy 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

Dzwonisz rekurencyjnie funkcja multiplyT, ale nie masz kontroli powrót. Następnie multiplyT (5,3,0) nie zwraca wartości w pierwszym wywołaniu, a funkcja następnie zwraca wartość undefined.

To prawda, że ​​stos jest uruchamiany, ale pierwsze wywołanie jest tym ważniejsze: musi uzyskać wartość z rekursywnej funkcji wewnętrznej, która zwróciła ostateczną wartość.

Fix kod w oddziale innego, dzięki czemu można powrócić wywołanie rekurencyjne:

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

mam wymyślić dobrego rozwiązania tego podczas pracy na jednym z moich projektów, w którym przemierzają kompleksowy obiekt JSON powrócić jakieś dane na poszukiwaniu 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; 
     } 
    } 
} 

Tutaj możemy uruchomić pętlę czasu, aby sprawdzić, czy recursed wywołanie funkcji zwraca wartość true lub nieokreślone.Jeśli zwróci coś innego niż undefined, zwróci dane.

Powiązane problemy