Jonas
Jonas

Reputation: 19642

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.

Upvotes: 1

Views: 324

Answers (5)

user2560539
user2560539

Reputation:

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.

Upvotes: 0

TheRealSuicune
TheRealSuicune

Reputation: 367

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

Upvotes: 1

Esailija
Esailija

Reputation: 140228

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.

Upvotes: 8

KooiInc
KooiInc

Reputation: 122936

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

Upvotes: 0

Yabada
Yabada

Reputation: 1758

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

Upvotes: 1

Related Questions