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.