Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Why is this Maximum Callstack error happening and how do I fix it?

I did some research on this error and it says it happens when the call stack has exceeded its cap, but what I don't understand is why this is happening. This error only appears when I run user2's showUsername method

Can someone please look at my code and tell me where I'm going wrong? https://w.trhou.se/1rxy8kwgex

4 Answers

Steven Parker
Steven Parker
231,153 Points

The method is currently calling itself, which creates a recursion loop. This is because there are two missing underscores:

        // ... in the constructor ...
        this._username = username;  // <-- underscore was missing
        this.password = password;
    }

    // Getters and setters
    get username() {
        return this._username;      // <-- underscore was missing
    }

Aaaaaaaah. That makes sense then. Ty

Wow, so rude.

Thanks for the quick reply. I tried both of the methods that you suggested and it prints a new error. When I try to call the method.

Uncaught TypeError: user2.username is not a function at <anonymous>:1:7

Steven Parker
Steven Parker
231,153 Points

Are you trying to call it like a function? Properties created by getters are accessed like ordinary properties:
user2.username:point_left: not :point_right:user2.username()

You're causing an infinite loop because user2.username (or any user.username for that matter) will recursively call itself

This happens because your getter for username is itself trying to get the username of itself.

So basically, you request user2.username, but doing so will itself request user2.username because user2.username is equal to user2.username, so to find out what user2.username is it needs to first know what user2.username is. Oh my god, will it ever stop? No it won't.

So what does this have to do with the callstack? Well, when javascript encounters a funcion, it will add it to the stack of functions to execute. Like a stack of pancakes. And much like a stack of pancakes, you add new ones to the top when you are done cooking, but you also take new ones from the top when you are ready for eating one. This is exactly how javascript handles the callstack. Any time it needs to run a function, it will add it on top of the call stack, and any time it's finished executing a function, it will continue to the next one.

The problem however starts when one function needs to run another function before being able to complete. So function a will need a value from function b before function a can complete. In this case, function a will be paused, and function b will be added to the callstack. Now function b will be evaluated first, and after that, it will give it's value to function a, which will then continue. This is normally fine and desired behavior, this is how javascript works. But what happens if function a needs a value from function a? Function a will keep adding itself to the callstack forever, until the javascript engine runs out of memory, and then it says "maximum call stack reached". Basically, you have been baking so many pancakes, your stack of pancakes hit the roof, and now you can't add any more pancakes to the stack.

(sidenote, it is possible for a function to call itself without causing an infinite loop, but that's a question for another time)

Great, so how do I solve this? Simple, avoid the recursion in the first place. Instead of

 get username() {
        return this.username;  // <--- this is a problem, because this.username calls itself
    }

do this

 get username() {
        return this._username;  // <--- this is fine, because this._username is not the same as this.username, infinite loop averted
    }

By the way, you are mixing prototypes and classes. Try to use one concept instead of both. This won't cause an issue, but it is bad practice and it will look unprofessional.