Lesson Wednesday

This is our fourth and final lesson on basic debugging with JavaScript. In this lesson, we'll use a tool called debugger to pinpoint and finally fix the last of the bugs in our broken Madlibs code.

Of the four debugging tools we're covering now, debugger is the most important tool to master. Pay close attention and make sure you understand the basics of using this tool. Don't worry - you will get plenty of practice with debugger. We recommend using this tool every time you are trying to solve an error in your code.

The debugger tool freezes execution of our code so that we can run our own experiments in the scope that the code is frozen in. This is very useful because we can drop a debugger directly inside our loop and then check the value of any variables. We can't do that if we just submit the form and try to then check the value of variables in the console because the function holding those variables has been completed and those variables are out of scope. We need to pause inside that function to actually see what's going on.

There are two ways to freeze our code using debugger - a great way and a not-so-great way.

The not-so-great way is to drop a debugger; statement directly in our code where we want the code to stop. It's a less convenient approach than the great way, but the more important thing is that you absolutely can't forget to remove the debugger; statement afterwards. It will freeze execution of your code whenever anyone uses it. As you can imagine, that would be a disaster for a production codebase. Even if you aren't putting your code in production, it's annoying to have to remember to remove it.

For that reason, let's focus on the great way instead. In DevTools, go to the Sources tab.

On the left, you'll see the file tree for our project - including a css folder, a js folder and our madlibs.html file. We can click on any of these files to see the source code. We want to look at the scripts.js file. The scripts.js code may already be open in the main pane of the Sources tab, but it's important to know how to navigate to the file you want.

Check the GIF below, which walks through the whole process - including adding breakpoints, which we'll discuss further in a moment.

First make sure you've chosen the right file to add a breakpoint to, then add the breakpoint.

In the GIF above, several things happen. First, we ensure that we are looking at the correct file by selecting it in the left-hand pane (the Page tab within the Sources tab). When we start creating projects with more files, it's especially useful to be able to switch between them in this pane.

Next, we can click on a specific line in our code to insert a blue arrow. This is a breakpoint, which means that our code will pause execution when it hits the line of code to the right of the blue arrow. The breakpoint should always be added to the line right after the line we actually want to evaluate. This is because we want to evaluate a line after it has run, not before - and the breakpoint will stop the code as soon as a line is reached (and before the code from that line is evaluated). As we can see, we can add as many breakpoints as we want. We can also click on a blue arrow to remove it.

This way of adding breakpoints is much easier than manually typing out a debugger; statement in our code - and we don't have to worry about deleting them once we are done because they are never added to our actual source code, anyway.

We can also make changes directly to our source code in this pane as well. Let's add a console.log() statement via the Sources pane in DevTools:

We can directly edit the code in the Sources pane. Here we make edits to `console.log()` statements.

In this example, we make some edits - we remove a console.log() statement that we accidentally left in our code. We also edit another console.log() statement so it will log "hey!" to the console. This is just to illustrate that we can make changes directly to our code from inside of DevTools. This is a great way to experiment with code because none of these changes are permanent. Also, when we do add console.log() statements, generally it's better to add them here - once again, we won't ever have to worry about remembering to remove them.

At this point, we just need one breakpoint (blue arrow) by line 10. Make sure that you've added a breakpoint to the correct line, then fill out the form and submit it.

In the GIF below, we are going to do several things. We'll summarize in a moment.

In this GIF, we stop at the breakpoint and then try out our code.

First, we submit the form. (The fields have been pre-filled.) As you'll see, highlighted values show up next to many lines of code. Any time a statement is evaluated, DevTools will helpfully put the value of the statement to the right of the code. This is an easy way for us to see the value of each of our inputs in the example above.

Now it's time to poke around in our code. The story isn't showing, but that's because we haven't reached this line of code yet:

$("#story").show();

Let's copy that value and paste it into the DevTools console.

Now our story is showing! We can evaluate any JavaScript code in the console including jQuery code that updates the DOM.

Next, we check what happens when we run $("person1").text(person1Input);. There are no updates to the DOM, which is expected - this is the broken line of code. We verify that person1Input is indeed what we expect it to be. We also try running this line of code to verify that it's working correctly: $(".person2").text("is this working?");. Indeed it is.

Well, let's do some experimentation here. It looks like $("person1").text(person1Input); is missing a . to denote that it's a class. So let's try inputting this code in the console: `$(".person1").text("does this work???");.

That does work correctly. So that was our issue - a missing .. We were able to experiment with the code in our application - including variables that are in scope at the point the code is frozen.

This is a very powerful feature of debugger. We can experiment with the value of variables and run any code we want within any local scope in our application - as long as our breakpoint is paused within that scope.

We've now fixed the final bug in our code. Make sure to actually make the update in VS Code - and remove any console.log() or debugger; statements that are still in the code. At this point, it should be clear that it's generally better to just use breakpoints and insert console.log() statements directly in DevTools.

Over the last four lessons, we explored several tools for debugging JavaScript in the browser. The most powerful of these tools is the last one - using breakpoints to hunt down bugs in our code. However, all of these tools can be very useful and it's important that you get familiar with each of them. If you are a good debugger, you are well on the way to being a good coder.

Using debugger


  • The debugger tool freezes execution of our code wherever we add a debugger; statement or a breakpoint.

  • The best way to add a breakpoint is to go to the DevTools Sources tab, click on the file you want to add a breakpoint to (in the left pane of DevTools), and then click on the line number in the source code to add a blue arrow (a breakpoint).

  • The breakpoint will pause execution of the code as soon as it's reached, so it should be added to the line after the one you want to evaluate and debug.

  • We can also make changes directly to the code in the Sources tab. This allows us to experiment without needing to change our actual code in Visual Studio Code.

  • We can click "Resume Execution" (the blue arrow) to go to the next breakpoint.

  • When our code is paused, we can go to the DevTools console and access any variables in our current scope. We can even write and run statements that use those variables.

  • Make sure to familiarize yourself with this tool. It's one of the most important debugging tools at our disposal.