Debugging JavaScript with Chrome Developer Tools

Written by pdp2 on 7th October 2015

Filed under: Tutorials

screenshot of my blog page being inspected

Most web developers are aware of Chrome’s Developer Tools, however, what I have found from working alongside other developers is that everyone uses them in different ways. I had the feeling that I wasn’t really getting the full benefit of using Developer Tools when debugging JavaScript so I decided to do some research.

Console API

The Console API has many methods that can be used and you can find more information on them here: https://developer.chrome.com/devtools/docs/console-api

If you have written any JavaScript code in the past you will probably be familiar with the Console API and in particular the following expression:

console.log(‘hello world’);

The previous statement logs the string “hello world” to the browser’s console. When debugging JS code this is one of the methods that I use most. If something is not working then one of the things I normally check first is if one of the variables or properties in the code is not returning what I expect it too.

For the first example, we will be using the console.log() method to fix an actual bug. Download the example files and then open index.html in example-1 in the browser. When clicking on the “See more” button a section of content below it should be shown, however, if you try doing this you will soon discover that it doesn’t work.

Open default.js in your text editor. At the top of the file we are setting some variables, then we are binding a click event to the value of the $trigger variable, which should be a jQuery collection containing the trigger button element. Lastly we are defining a function called toggleContent which is responsible for showing and hiding the content beneath the button.

Seen as nothing is happening when we click the button, one of the things we can check is if the click handler has been bound correctly and if the toggleContent function is being called. In default.js place the code console.log(‘here’); inside the toggleContent function before any of the other code.

Reload the page and open up the Developer Tools. This can be done in a few different ways which I have listed below:

  • Press F12
  • Press Ctrl + Shift + I
  • Right click anywhere on the page and select “Inspect Element”

Select the “Console” tab from the menu. When you click on the button the string “here” is output to the console so this means that the click event has been bound correctly and the toggleContent function is being called.

Now we are going to check the value of the $content variable as this is what the jQuery slideToggle method is being called on. Go back to default.js and change the value inside the console.log() to $content. Reload the page and then click the button again and you will see a jQuery object has been output in the console. Open the object by clicking on the arrow to the left so that we can see the properties. You will notice that the property length has a value of 0. This means that no HTML node was found using the selector that we used. From looking at the selector property we can see that the selector being used is “.contents”. Look back at index.html and you will see that the class name of the element is in fact “content” without the “s” so the selector we are using is incorrect. In default.js remove the “s” from the selector for the $content variable and then reload the page. Try clicking the button again and you should find that the visibility of the content is now being toggled as intended.

As you can see logging values in the console can be helpful when debugging JavaScript code, however, this requires you to jump back and forth between your code and the browser. In the next section we will be using breakpoints to diagnose the issue by using just the browser.

Breakpoints

Open index.html in the example-2 folder from the exercise files in Chrome. On the page you will see a trigger button and a green box. Clicking the button should toggle the class of the box element causing it to change colour, but, as you will soon find out, it doesn’t work.

Open up the Developer Tools and select the “Sources” tab. Then, expand the scripts directory and select the file named default.js. In the center column you will be able to see the JavaScript code. Notice that the line numbers appear on the left hand side of the code. By clicking one of the numbers you can add what is referred to as a “breakpoint”. This means that the code will be paused when it reaches that particular point. When a breakpoint is added a blue tag will appear on the line number.

As with the previous example, the first thing we can try checking is if the click event has been bound correctly. This time though, instead of having to go back to the code in our text editor we can use a breakpoint to verify if the function bound to the click event is being called. Place a breakpoint inside the click handler on line 6 and then click the trigger button again. You will notice that an overlay is added to the page and a little box appears in the top center with the words “Paused in debugger” and two buttons to the right. The fact that the code has been paused at this point when we click the button indicates that the function has been called and the click event has been bound. Click the blue play icon and then click on the blue tag on the line number to remove the breakpoint.

Next we can check if the value of the $box variable actually contains a reference to the box HTML node. Place a breakpoint inside the toggleBoxClass function on line 12, but this time after you have placed it right click on the blue tag and select “Edit breakpoint” from the context menu. This feature allows you to insert an expression to be evaluated when the browser gets to that particular point in the code, if the expression evaluates to true the execution of the code will be paused, otherwise it will just carry on. In the box type $box.length === 0 and then press enter.

This means that the code will only be paused if the $box variable doesn’t contain a reference to the relevant HTML node. If you try clicking the trigger button again you should find that the execution is paused which means we have found our problem. By looking at the selector used on line 3 of default.js and then referring to the markup in index.html we can see that once again the selector is wrong. By changing the selector to “#box” we can see that the example works as intended.

Event Listener Breakpoints

If you are unsure where in the code a particular event is being bound you can use the Event Listener Breakpoints to pause the code when an event occurs. If you expand the section you will see that you can listen to many different types of events. For the purpose of this example expand the “Mouse” section and then check the “click” event. When you click on the trigger the code will pause. Unfortunately I haven’t been able to work out how this can be used to see where this event is handled in my own code so I welcome any suggestions you have.

Call Stack

While you have an active breakpoint and the execution of the code is paused it is possible to view the current call stack. If you look at the right hand side of the “Sources” panel you will see a section called “Call Stack”. Still looking at example-2, insert a breakpoint on line 12 and then click the trigger button. The code will be paused and if you expand the “Call Stack” section you will be able to see a list of the functions that have been called up until the breakpoint you have specified. In this case we can see the toggleBoxClass function inside which we have placed the breakpoint, and, after that we see “anonymous function”. Click on that section and the line on which the toggleBoxClass function is called will be focused. If you follow the trace further down we go into where the event is dispatched from within the jQuery code.

Watch Variables

This is a handy way of keeping track of the values of certain variables at specific points in the code. Again on example-2, from the “Sources” panel insert a breakpoint on line 8 of default.js. Then, find the “Watch” section on the right hand side and press the plus icon. Inside the field that appears type $box and press enter. You will see that under the “Watch” section the $box property appears with the value . We are now watching that variable so if we now click the trigger button again you will see that when the code is paused on line 8, the value of the $box variable is updated.

Step Over, In, Out

Once the code is paused at a breakpoint it is possible to step through lines of code or step into and out of functions. Open index.html from example-3 in Chrome and activate the Developer Tools. Then go to the “Sources” tab and select the default.js script. This JS code shrinks the box on mouseenter and enlarges it again on mouseleave. Set a breakpoint on line 15 just inside mouseLeaveHandler. Mouse over the box and then mouse out and the code should pause at line 15. On the right hand side just above the “Watch” section there are some buttons that look like this:

screenshot of chrome dev tools

The first button with the arrow looping over the dot is the step over button. This makes the browser go to the next executable line of code. Press this and you will see that the code is now paused on line 16. If you pressed the button again you will step over the enlargeBox function, however, if you press the icon with the arrow pointing down towards the dot (the step into button) then you will be taken to line 26 inside the enlargeBox function. You will notice that on that line there is a jquery method called removeClass. Press step into again and you will be take to where the removeClass method is defined in the jQuery code. You can then press the step out of button (arrow pointing upwards away from the dot) to get back to the next line in default.js.

Blackboxing

If when using the step into function button you want to prevent Developer Tools from taking you to a third party script you can choose to “Blackbox” the script. You can do this by navigating to the file in the “Sources” tab and then right clicking on the code panel and selecting “Blackbox script” from the context menu. Now when you attempt to step into a function which is defined in the script you have blackboxed the browser will just jump to the next executable line.

Conclusion

Debugging can be tricky and time consuming and everyone has a different approach. Hopefully this overview of the Chrome Developer tools will have given you some ideas on how to approach debugging. I’m sure there are many other ways that you can use these tools to help you when fixing bugs so if you have any suggestions please let me know.