简体   繁体   中英

Javascript factorial function stack overflow

Why does the following javascript factorial function throw a stack overflow error when called?

function fact(n) {
    return function () {
        var n = n;
        return (n < 2) ? 1 : (n*fact(n - 1));
    }();
};

When I remove the line var n = n; it works as expected. Also, I'm aware that the inner function is redundant, it's just there to trigger the error.

var n = n in that situation effectively does n = undefined because the formal parameter n and the declared n are from different scopes. In your comment declaration n and formal parameter n are in same scope so it's not the same situation.

undefined < 2 is always false, so it keeps calling fact forever.

var n = n <- two problems here.

1: You have two variable with the same name, how could they be differenciated

2: var n = n is equal to var n = undefined , witch result in false return and loop forever

What you want to do is :

function fact(n1) {
    return function (n1) {
        var n = n1;
        return (n < 2) ? 1 : (n*fact(n - 1));
    }();
};

The line var n = n; isn't necessary, because it's defining a ' new ' variable called n , and setting it to n .

Your function is returning the result from an anonymous function, which isn't necessary.

The parameter n is in the main function, not the anonymous function.

I also spaced the * symbol, in (n*fact(n - 1))

  • The original code:

     function fact(n) { return function () { var n = n; return (n < 2) ? 1 : (n*fact(n - 1)); }(); };
  • The updated code:

     function fact(n) { return (n < 2) ? 1 : (n * fact(n - 1)); };

@ Esailija already explained the cause. Try:

function fact(n) {
  return function(n) {return n && n > 1 && n*(fact(n-1)) || 1;}(n);
  //                                                            ^ pass n here
};

Or use the closure:

function fact(n) {
  return function() {return n && n > 1 && n*(fact(n-1)) || 1;}();
};

Or indeed just use:

function fact(n) {
  return n && n > 1 && n*(fact(n-1)) || 1;
};

You only need to omit the re-declaration of var n and the code is working fine. But i would go for a for loop in this one, it makes half the time.

 function fact(n) { return function () { return (n < 2) ? 1 : (n*fact(n - 1)); }(); }; let startDate = performance.now(); console.log(fact(170),`fact(170) took: ${(performance.now()-startDate)} milliseconds`); function fact2(n) { let result = 1; for(let i = 2; i <=n; i++) { result *= i; } return result; } startDate = performance.now(); console.log(fact2(170),`fact2(170) took: ${(performance.now()-startDate)} milliseconds`);

PS: the timing was made out of curiosity. I wanted to see a difference between the timed needed in this answer on a somehow relative answer that involved Julia programming language.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM