JavaScript Debugging for Beginners

date2014-05-18

Note: the interactive parts of this post do not work any more after years of migrating to different static site generators and much of the code being out-of-date.

I set out to write a post about JavaScript debugging for beginners because I often see people struggling with this and want to help. I hope this post provides some useful information to help you get started. I tried to cram a lot in here, so it is just a start. I hope to write some follow-up posts in the future that dig into more detail.

Let's start with some assumptions for this post before we get started:

  • This is for browser-based JavaScript debugging. If you're looking for help with node.js, you're in the wrong place.
  • This post assumes you are at least a little familiar with writing JavaScript in the browser. You don't need to be an expert, but I won't be explaining js basics here.
  • This post assumes you have a basic grasp of what debugging is as a programming concept.
  • You'll get the most of this post by being hands on. Try clicking the buttons. Try inspecting things. Try copying and pasting code to see how it works.
  • I make some cheesy Dune references in this post. I regret nothing.

Note: This is a pretty interactive post. You may find it useful to open it in two tabs. One for you to reference the writing and one for you to play around with.

Disclaimer: The JavaScript I wrote for this post is pretty quick and dirty. It is not an example of good coding practices. The point of this post is to teach you how to debug js, not how to write good js. Perhaps that is a post for another day.

Table of Contents

Alert

The alert displays a dialog with the specified string value and an "ok" button to dismiss it. It will stop the JavaScript from continuing until you click "ok".

alert("Hello! I am an alert.");
Screenshot of a browser alert.

This is useful for debugging because you can set the alert value to something meaningful.

// I want to know if I reach this part of the code.
alert("I am here!");
// I want to know the value of foo in this part of the code.
alert("Foo: " + foo);

If you accidentally put an alert in a place that runs a lot of times, it can get annoying really fast. In the past, I occasionally had to kill a browser and restart it.

// I heard you like alerts...
for (i = 0; i < 100; i++) {
  alert(i);
}

Thankfully, we are no longer in the past. Chrome will help you out if you accidentally make too many alerts. Clicking the "Prevent this page from creating additional dialogs" checkbox in the alert will do exactly what it says.

Screenshot of a browser alert with a 'prevent additional dialogs' checkbox.

Way back in the day, alerts were one of the main tools people used to debug their JavaScript. Unfortunately, the alert is a very limited tool. It can only display strings.

// I want to see all the H2s on the page.
alert($("h2"));

Well, that's pretty useless.

Screenshot of a browser alert for an object.

Why am I mentioning alerts if they're limited and painful to use? Because occasionally you still need to fall back on this old tool.

Even when better debugging tools became available, there were still occasions where I had to debug my JavaScript using alerts (insert angry rant about IE6). Be thankful that we are mostly beyond that time. I have recently used alerts for debugging on a mobile device where I was not able to get the debugging tools to work.

Developer Tools

Welcome to the future! Well, sort of. Developer tools have been around for years. However, they've grown and added a ton of useful new features that many people are unaware of or don't know how to use. Developer tools are invaluable for JavaScript debugging. I'll spend the rest of this post talking about how to use them.

For the duration of this post, I will be giving advice about using the Chrome developer tools. They have been my developer tools of choice for several years now. If Chrome isn't for you, many other modern browsers have similar tools, so a decent amount of this post should still be useful.

Before you can use the Chrome developer tools, you have to know how to access it. You can open it in a few different ways.

You can open it via keyboard shortcuts:

  • Windows/Linux: ctrl + shift + I
  • OSX: cmd + opt + I

You can open it from the chrome menu. Screenshot of opening the chrome developer tools.

You can open it by right-clicking the page and inspecting an element. Screenshot of context menu for inspecting an element.

It looks something like this. We're going to start on the "Console" tab, so click that tab if you're not already there. Screenshot of developer tools console tab.

Console

The console is an incredibly useful part of JavaScript development. In many programming languages, you do debugging and logging in the terminal. The console is the equivalent for JavaScript in the browser.

Errors

The console tab shows JavaScript errors.

Screenshot of developer tools js error.

It also shows you where the error originated. Click the underlined file name and line count to the right of the error to be taken to the origin.

Screenshot of developer tools line of js error.
<input
  type="button"
  onClick="alert(THE SPICE MUST FLOW);"
  value="Click to create an error"
/>

This line seems to be the problem. Can you figure out what's wrong? How should we fix it?

Click me to toggle the solution

The string inside the alert does not have quotes around it.

We can fix it by putting quotes around the text. Try this fixed example. Right click the button element and inspect it to see the modified code.

Command Line

The console has an interactive command line that can be useful for debugging. Below are some examples. Give these a try in your console.

You can do some basic JavaScript.

// Try some math.
2 + 2;
// How about some string manipulation
"the golden " + "path";
// You can even create an alert
alert("Muad'Dib!");

And some more complicated JavaScript.

// You can create variables.
var arr = [1, 2, 3];
// You can add multiple lines by pressing shift + enter.
for (var i = 0; i < arr.length; i++) {
  arr[i] = arr[i] * 2;
}
arr;

The console provides a bunch of helper functions. See the command line api reference for more information.

// You can look up elements via css selectors
$$("h2");
// Or xpath
$x("//h2");

You can access libraries defined on the page. For example, this page has jQuery.

// You can make the page red.
$("body").css("background-color", "red");
// That's a bit much. Let's put it back.
$("body").css("background-color", "");

You can access variables in the current context. We'll talk about this more later.

// The current context.
this;
// Access a variable I set in this context.
exampleVariable.join(" ");

console.log

The console.log method outputs a message in the console.

console.log("I am logging to the console.");
Screenshot of a console log in the developer tools.

This is basically the JavaScript equivalent of using a print method for debugging. Just like an alert, we can use it to output values or check that we reach certain places in the code.

// I want to know if I reach this part of the code.
console.log("I am here!");
// I want to know the value of foo in this part of the code.
console.log("Foo: " + foo);

Unlike an alert, console.log does not stop the JavaScript from continuing. It logs to the console and continues on its merry way.

// This isn't nearly so annoying with console.log.
for (i = 0; i < 100; i++) {
  console.log(i);
}

Alerts could only output strings, which limited the information they could provide. Console.log has no such limitation.

// It can output dom elements.
console.log($("h2"));
// It can output objects.
console.log({
  book: "Dune",
  characters: ["Paul", "Leto", "Jessica", "Chani", "sandworms"],
});

This is just the beginning. There is a lot more you can do. I recommend reviewing the console api reference for more information.

The console logging provides enough for you to get by, and some developers stop there with their JavaScript debugging skills. However, it's not always the best tool for the job. Debugging complex JavaScript using console logging can be slow and painful. Thankfully, there are even more debugging tools available to you.

Interactive Debugger

The Chrome Developer tools has an interactive JavaScript debugger that provides a rich toolset useful for debugging your code. I find this especially useful for complex JavaScript code and code that interacts with other libraries.

You can start the debugger at a specific point in your code by calling debugger.

// I want to start debugging here.
debugger;

The debugger will only do something when the developer tools are open. Close the developer tools and click the button. Hmm, it looks like nothing happened. Now try opening the developer tools and clicking it.

You should see something like this. Now you can start debugging! Screenshot of start of debugging.

If you click the "continue" button , it will continue running the code until it hits another breakpoint. Again, doesn't seem like much happens. Let's try something else.

If you click the "step over" button , it will step over the next line of code. Do this a few times.

It turns out this code does do something. It just happens so fast, we couldn't see it before. Screenshot of debugging. The body background is red.

What if you're interested in finding out what the makeItColor function does. Step over until a call to that function is highlighted. Then click the "step into" button to step into that call. You can click the "step out" button to step out of the call.

The panel on the right includes useful information about your current location in the code. Screenshot of debugging.

You can find out the values of code in the debugger by highlighting it and hovering over it. Screenshot of debugging..

You can open up a console on the sources tab by hitting esc. This can be useful for playing around a with the variables and other information in that context. You can dismiss the console by hitting esc again. Screenshot of debugging with console.

You can manually add breakpoints by clicking the line number of code where you want to stop. Screenshot of adding a breakpoint when debugging.

Now the code will break on this line. You can hit continue a few times to go through all of the color changes to the page background. You can remove a breakpoint by clicking the line number again.

I'm not going to go into much more detail about using interactive debugger. The debugging javascript documentation already does a great job of this, so it seems silly for me to duplicate it.

Libraries and Minified Code

Sometimes, your debugging needs to dig into interactions with other libraries you depend on.

On this page, I'm using the jQuery library, so we'll use that as an example. Open the developer tools. Go to the sources tab. Find the jQuery library, and click on it to take a look.

Well, this is pretty impossible to read. This code is minified. Screenshot of jquery minified.

If you click the braces at the bottom of the developer tools, they will "pretty print" the code. It makes it a little bit more readable, but it's still difficult to decipher. Screenshot of jquery minified with pretty print.

Minified code is useful for production, but very difficult to deal with when debugging in development. Thankfully, many libraries will let you use an unminified development version of the code. You can switch to this during development to make it easier to debug problems. Be sure to switch back to the minified code before you go to production.

<!-- For production -->
<script
  src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"
  type="text/javascript"
></script>
<!-- For development -->
<script
  src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.js"
  type="text/javascript"
></script>

Click this button to switch the page to using development jQuery.

Go to the sources tab. Find the new jQuery library, and click on it to take a look.

Look! We've got meaningful variable names and commented code! Much better for debugging. Screenshot of development jQuery.

Let's try it out!

Go to the line in makeItColor where we are using jQuery functions. Screenshot of debugging.

Step into the code. This is stepping into $('body') to find and return the body element. Screenshot of debugging jQuery.

Step out and then step into again. This is stepping into .css('background-color', 'color') to set the background color of the element via css. Screenshot of debugging jQuery.

Hopefully, you won't have to debug the libraries you work with very often. However, it's useful to understand how to do so when things behave unexpectedly. Sometimes you'll even find a bug in the library you are using.

AJAX Requests

The network tab of the developer tools is really helpful for testing issues related to ajax requests.

Let's take a look at an example viewing a twitter timeline.

  • Go to @horse_js (or some other twitter user you like better).
  • Open the Chrome developer tools.
  • Go to the network tab.
  • Click on the filter icon .
  • Click the XHR filter option (it stands for XMLHttpRequest) - that will limit us to the ajax request we're looking for.
Screenshot of the network tab.
  • Scroll down the page to trigger an ajax request for more tweets.
  • A request with "timeline" in the name should appear.

The Headers tab provides you with information about the headers sent and received in the ajax request. There's a lot of interesting information here you can dig into. Take a look. Screenshot of the network headers tab.

The Preview tab lets you preview information about the ajax response. That means the developer tools format it a bit for you. Screenshot of the network preview tab.

The Response tab lets you see the ajax response as text without the developer tools doing anything special to it. Screenshot of the network response tab.

The Cookies tab shows you the cookies associated with the request. Screenshot of the network cookies tab.

The timing tab provides you with information about how long the parts of the ajax request took. Screenshot of the network timing tab.

Let's try it out!

We have a simple script that is supposed to load some quotes from data.json via an ajax request and create a list of the quotes in the section below.

Dune Quotes

Let's try it out.

Hmm, something has gone wrong. Can you figure out what?

Click me to toggle the solution

The file being requested has a typo, resulting in a 404 request.

Screenshot of ajax 404 error in network tab.

The mistake is in the onClick of the button. It calls dataa.json instead of data.json. We can fix it by calling the correct file. Inspect the button element to see the fixed code.

Performance

Debugging performance issues in JavaScript could be a whole post by itself. For now, I'll point you to some useful information if you want to dig into this topic sooner:

Mobile

You can emulate some mobile interactions using the developer tools, so that you can do debugging on your desktop browser. Check out the mobile emulation documentation for more information.

You will also likely need to do some debugging with real (or simulated) mobile devices. Check out these posts for some more information.