Open your Inspector
I’m going to call everything, from here on out, the inspector. Each browser has a different name, in Chrome its called the Web Inspector, Safari calls it the “Safari Developer Tools”, Firefox has Firebug, and even Internet Explorer has a kind of “Developer Tools”. The majority of these techniques, as one would expect, are found on Chrome, Safari and Firefox, but Internet Explorer 9 at the moment has only just started to catch up after being dormant on the inspector front for, well, forever.
The inspector is usually opened by right-clicking on a “blank” area of the screen and selecting Inspect Element or something along those lines based on your browser. In IE, press F12.
Using the console
Let’s take a look at something we can do in console right here on this site. This site uses jQuery, so I’m going to run a through commands and we can see the results:
$(document).trigger('customevent') within the console.
While the console offers some powerful tools, creating breakpoints
through the use of the
debugger statement actually turns your
a look into how that works and how to leverage the (many) available
features. We’ll start by making a basic HTML page which will include
1 2 3 4 5 6 7 8 9 10 11
1 2 3 4
Open index.html in your browser. Initially, you should notice if you don’t have your web inspector open that nothing happened. Most inspectors will ignore things like debugger statments unless the inspector is open. However, if you open your inspector and hit Refresh on your browser, you likely will get something which appears like this:
Let’s take a look at our surroundings.
The browser is telling us the execution is paused. The page has
stopped “working” until we tell it to continue on. Under the Sources
panel we can see which line of code we’ve paused on, which, when using
debugger, is always on the debugger line itself. While this alone is
partially interesting, there’s a lot more power to extract here. We
want to use the console and play around. While you could switch to the
console tab itself, wouldn’t it be better to have the console right
Esc to get the console to appear.
Now we’re cooking with fire! With the console we can do anything to
the current state. We could rewrite
foo, delete it, create a new
variable, inspect other variables, etc. For now, let’s take a look at
the value of
Viewing the value of variables mid-way through execution is an incredibly
powerful for debugging. As mentioned earlier, we can anything we
foo’s value for fun
Here we set
c. Not exactly mind blowing, but we’re just
getting our feet wet. But what if we’re done fooling around and want
the rest of the code to execute? For that, we’ll want to take a look
at the debugging tools.
- Resume script execution Resumes your script if it has been paused due to a debugger statement or breakpoint.
- Step over next function call Steps to the next line of code, attempting to remain in the same current scope if possible.
- Step into next function call Dive into the next function we encounter. Where as the previous button will attempt to remain in the same scope, this function will bring us into the next function we encounter.
- Step out of the current function If you’re inspecting a function you’re not concerned about, this will escape you out to its parent scope.
- Deactivate all breakpoints Removes all breakpoints, though not
debuggerstatements. Especially useful once you’re finished debugging and want to get on with your life.
In this case, let’s hit Resume script execution to move on. Because we have two debugger statements in our code, we expect to get halted again on the second statement.
This time around we see that our
foo = 'b' code has been executed,
and if we inspect
foo we see it is currently set to
You can either press the Resume Script Execution button or close the web inspector to have the page finish out.
Similar to the
debugger statement, the inspector supports
breakpoints. Breakpoints have a few advantages:
- They do not pollute your code with dangerous
debuggerstatements which could accidentially be committed.
- They support conditional breaking.
- They allow you to debug code that perhaps isn’t even yours to edit.
However, breakpoints have one minor disadvantage: you need to find the line to break on using the Source panel, which can sometimes be inconvenient and counterintuitive, especially if you’re already editing the code in question with your editor.
There is no right or wrong way in this case, they’re two sides of the same coin. It’s best to understand both methods.
Let’s edit our scripts.js file to make it look like this:
1 2 3 4 5 6 7 8
With your inspector open, open index.html again and let’s take a look at the console.
This looks fantastic, but we’re getting that nasty
Why is that? Well, let’s start by putting in a breakpoint.
Creating a breakpoint
Under the Sources tab, click the line number where we want to create
a breakpoint (breakpoints are essentially identical to
statements). You should see something identical to the image below:
Refresh the page and let’s see what happens.
We can see that our execution has paused on our breakpoint. We can
play around in the console as well (remember to bring it up when
you’re under the Sources tab by pressing
Esc on your keyboard). If
you test our
i value we can see it is currently
is properly set to Bill.
We can continue the script by pressing the Pause script execution button, which will be triggered each iteration throughout the loop. You’ll notice that the script outputs John, then goes on one more time. There’s our problem!
However, if we knew the problem was with the value being
wouldn’t it have been better to only break when
undefined? It would have sure saved us a lot of clicking, and imagine
if this was a much larger array!
Create a conditional breakpoint by right-clicking the breakpoint and selecting Edit Breakpoint…. You will be presented with this dialog:
Here we can enter in whatever condition that needs to evaluate to
true for this breakpoint to be fired, and here we have the single
biggest advantage breakpoints have over debugger statments.
Enter your condition like so and press
A conditional breakpoint appears as an orange flag:
Note: I sometimes find the browser can be extremely flakey in accepting the statement. If you are finding the orange flag denoting the breaking is a conditional breakpoint is not appearing, try to remove the breakpoint entirely and recreate it. Don’t click “outside” the dialog box to confirm - that never seems to work. Always press enter.
Refresh the page again and let’s see what happens.
The script has run, and we can see in the console the breakpoint has
been skipped for all counts with the exception of when our statement
returned true, when our
names[i] was undefined. That’s a lot cleaner
and easier to debug!
Examining the interface
Of course the main script area and console are not the only visible items on the Sources tab. There’s also the area off to the right which contains some extremely powerful tools.
I guarantee if you’re not using these at the moment, they’re about to fundamentally alter the techniques you will use to debug.
Create a watch expression when you find yourself debugging and
constantly wanting to know the value of a variable. Using the same
code above, you could add a
names[i] watch expression and, by
setting a normal breakpoint on the console log, watch each value as it
ticks by (useful if you were not already logging the value to the
Adding the expression:
Refresh the page with the breakpoint set to easily see the content of the variable:
TL;DR Use watch expressions when you find yourself investigating the same variable over and over again while debugging.
The call stack will be very familiar to anyone who has worked in compiled languages equipped with IDEs. The call stack is essentially the functions or methods the browser has executed to get to the current line of code.
The call stack answers the question of, “How did this line of code get executed?” Even better, you can hop back through to the parent function(s) and view their current state(s) as well.
Let’s set up an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
This script will output first names with random last names to our console. Nothing special, but it gives us a tiny example to play with.
Let’s start by putting a breakpoint on line 8.
Refresh the page and look at the call stack item to the right.
What we have here is a list of functions we had to run through to get
to this item, the top most being the most recently run function. In
this case, we find ourselves in the function
line 8 of scripts.js, which was called by
scripts.js line 14, which itself was called by an anonymous function
(in this case, nothing) in scripts.js on line 19.
First, this gives us an immediate understanding of the order of execution and what happened to get us to where we are. This alone is invaluable, but there’s more.
If you actually click on one of the other stacks, in this case
processNames there in the Call Stack window, your scope will be
brought to that point in time. You can actually inspect and view which
variables are currently set.
The scope variable window shows exactly what variables exist within the current scope. While it doesn’t add any additional functionality, it can be nice to simply glance over at the scope variable window to quickly view the value of a variable.
Using the previous example with execution being paused at line 8, we
can quickly see the
firstName is set to Peter and
being set to Jordan.
DOM breakpoints are a powerful tool if you’re not sure what piece of code is modifying an element. Let’s set up an example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
1 2 3 4 5
Next, we’ll create our DOM breakpoint. To do this, find the
container element which encapsulates the element(s) you’d like to
monitor for changes. In our example, since our code is going to remove
<p>Loading...</p> item, we’ll want to assign the DOM breakpoint
.content element by specifying we want to break on Subtree
Next, click on the Load Content button, and let’s see what happens:
Script execution has been paused and the browser will display the Sources tab. The most interesting thing to us, at this point, is the call stack. We can see from the call stack there are a number of jQuery functions which are being run to begin DOM modification. But what line of ours actually triggered the change?
Looking at the call stack, we can see there is a reference to scripts.js on line 3. Click on that.
Here’s the line that we wrote which is triggering the call to modify that DOM element! This can be a highly useful tool if you’re unsure what line of code is making modifications to your DOM.
Good (bug) hunting!