loading...
Cover image for Oops, I did it again: A guide to debugging common JavaScript errors

Oops, I did it again: A guide to debugging common JavaScript errors

aspittel profile image Ali Spittel ใƒป4 min read

Writing JavaScript code can sometimes make us feel like running, hiding, or just being scared. But, with some debugging tips we can get in the zone and then dance until the world ends!

TypeError: Cannot read property "lucky" of undefined

let girl = {
    name: "Lucky",
    location: "Hollywood",
    profession: "star",
    thingsMissingInHerLife: true,
    lovely: true,
    cry: function() {
        return "cry, cry, cries in her lonely heart"
    }
}

console.log(girl.named.lucky)

This code throws the error "Uncaught TypeError: Cannot read property 'lucky' of undefined". In our girl object, we don't have the property named, though we do have name. Since girl.named is undefined, we can't access a property on something that doesn't exist. So, as is true for the girl named Lucky, something's missing from our life (or object). We would want to change girl.named.lucky to girl.name, and we'd get "Lucky" in return!

A property is a value in a JavaScript object. You can read more about objects here.

Steps to debug TypeErrors

TypeErrors are caused by trying to perform an operation on something that doesn't have a data type that matches up with said operation. So, trying to run .bold() on a number, retrieve an attribute on undefined, or trying to run something like a function that's not a function (for example girl() would throw an error -- girl is an object, not a function). On the last two, we'd get "Uncaught TypeError: yourVariable.bold is not a function" and "girl is not a function".

In order to debug these errors, you need to check your variables -- what are they? What is girl? What is girl.named? Is it what it's supposed to be? You can check this by looking at your code, console.log-ing your variables, using a debugger statement, or just typing the variable into the console and seeing what it is! Make sure you can perform the action on the data type of the variable. If not, cast the data type of the variable, add a conditional or try/catch to only run that action sometimes, or run the action on something else!

Stack overflow

According to the songwriters for "Baby One More Time", the "hit" in "Hit me baby, one more time" refers to a call, so Britney wants her ex-partner to call her one more time. Which will probably lead to more and more calls in the future. This mirrors recursion -- which, if the call stack size is overflowed, will cause errors.

These change by browser, but can look like:

Error: Out of stack space (Edge)
InternalError: too much recursion (Firefox)
RangeError: Maximum call stack size exceeded (Chrome)

This can be caused by not having a recursion base case, or having a base case that never fires.

function oneMoreTime(stillBelieve=true, loneliness=0) {
    if (!stillBelieve && loneliness < 0) return
    loneliness++
    return oneMoreTime(stillBelieve, loneliness)
}

In the above function, stillBelieve never becomes false and loneliness keeps increasing, so we keep recursively calling oneMoreTime without ever exiting the function.

If we instead make it so that Britney relies on her friends, instead decreasing her loneliness, and she stops believing in the relationship, she'll stop wanting her ex-partner to call.

function oneMoreTime(stillBelieve=true, loneliness=0) {
    if (!stillBelieve && loneliness < 0) return
    loneliness--
    stillBelieve = false
    return oneMoreTime(stillBelieve, loneliness)
}

There's a similar issue with infinite loops, though instead of getting an error message, our page usually just freezes. This happens when we have an un-terminated while loop.

let worldEnded = false

while (worldEnded !== true) {
  console.log("Keep on dancin' till the world ends")
}

We can fix this in a similar way!

let worldEnded = false

while (worldEnded !== true) {
  console.log("Keep on dancin' till the world ends")
  worldEnded = true
}

Debugging infinite loops and unterminated recursion

First, if you're in an infinite loop, quit the tab if you're in Chrome or Edge, and quit the browser window in FireFox. Then, do a check on your code: is there something that's glaringly creating the infinite loop/recursion? If not, I would add a debugger statement to the loop or function and make sure the variables are what they should be in the first few iterations -- you'll probably notice a pattern of something being off. In the above example, I would put a debugger in the first line of the function or loop. Then, I'd go to the debugging tab in Chrome, look at the variables in Scope Then, I'd click the "next" button to see what they are after an iteration or two. Usually that will get us to the solution!

This is a great guide to debugging with Chrome's DevTools, and here's one for FireFox.

Uncaught SyntaxError: Unexpected identifier

Potentially the most common category of errors in JavaScript is SyntaxError's -- these mean that we aren't following the syntax rules of JavaScript. To follow the sentiment of Britney in "Everytime", JavaScript is saying "I guess I need you baby" to our missing parenthesis, brackets, and quotation marks.

I would make sure you have a good text editor theme or extensions installed if you struggle with these types of errors -- Bracket Pair Colorizer helps color code braces and brackets, and Prettier or another linter can help catch these errors fast. Also, make sure to properly indent your code and keep codeblocks short and as un-nested as possible. This will make debugging any issues easier!


Now, with your new debugging skills, you can feel a little stronger than yesterday at JavaScript. If you are thinking Gimme More pop culture code references, here's thank u next: an introduction to linked lists.

Posted on by:

aspittel profile

Ali Spittel

@aspittel

Passionate about education, Python, JavaScript, and code art.

Discussion

markdown guide
 
 
function oneMoreTime(stillBelieve=true, loneliness=0) {
    if (!stillBelieve && loneliness < 0) return
    loneliness++
    return oneMoreTime(stillBelieve, loneliness)
}

This is poetry.

 

First, if you're in an infinite loop, quit the tab if you're in Chrome or Edge, and quit the browser window in FireFox.

FireFox is a lot friendlier than this - you don't need to close the whole browser and you get a nice, friendly message:

too much recursion indeed!

 

Big fan of the Bracket Pair Colorizer extension! Before, I didn't know that something wasn't right, and it definitely gives you a sign!

 

I didnโ€™t know about this extension. Iโ€™m totally going to try it out. It seems like it would save me a bunch of time.

 

So now the question is which of the referenced songs am I listening to first...

I've always been partial to Everytime :)

 
 

Nice one Ali! We recently started using Prettier on one of our projects and I love it - it catches silly mistakes and quells syntax debates ๐Ÿค˜ thanks as always!

 

const Ali = {
Name: 'Ali',
LovesBritney: true,
ShoutOut: function(){
console.log('Ali is awesome');
}

Ali.ShoutOut();

๐Ÿ˜…

 

Loved the way you explained the full stack issue, the rest I had a basic info about!
Still learnt something new ๐Ÿ˜ƒ

 

It's wonderful!!!
Sometimes these errors makes anyone Crazy, but Everytime I got these errors, I'll remember this text.

 

#britneyspears

Sorry, just can't help myself when I saw the title...

 

Read this last night and "Lucky" was stuck in my head all day today

 
 
 

This post is great! Ali has tons of info here with links to other resources too. This is a great resource for learning about why some of these really common errors happen. Nice work!

 

I need to write a post on a great follow up to this: debugging closures. I'm reminded of a big blocker I encountered when trying to debug an inner function one time.