Tom MacWright

tom@macwright.com

JavaScript Diagnosis

Photo of a dirty alley in DC

Let’s dive into errors in more depth: with the features built into the browser you use today, you can stop time, inspect values of variables as they change, and understand the call structure of your code.

Previously, I described the kinds of errors in JavaScript: understanding them is a prerequisite.

The other thing you’ll need is Google Chrome. That’s because this is a specific, visual guide to one specific kind of developer tool. There are similar implementations in Firefox and other browsers: I would love if anyone wants to contribute a version for another browser: diversity is good.

Opening the Developer Tools

The first step is opening the developer tools: this is a panel that usually sits below a webpage and gives you x-ray vision into its inner workings.

There are three different ways to open the developer tools: inspecting an element, clicking the toolbar menu, and hitting cmd-option-i (or ctrl-option-i on non-Macs)

Getting the Details

Now that you’ve successfully opened your developer console, let’s move on to looking at a bug, in detail.

The basic parts of a bug are as follows: each gives you a different perspective on its cause and the potential solution

  • type, for instance SyntaxError
  • message, like “could not access property foo of undefined
  • filename & line number, where the error occurred
  • call stack, or a list of functions calling each other that led to the error

We’ve reviewed type in the last post.

Error messages vary: there are lots of built-in error messages in JavaScript, some of which are helpful. Sometimes just by seeing an error message you’ll have a good idea of what to fix, but usually not.

The part where developer tools get really helpful is the filename, line number, and call stack: they’ll let you know where it happened, but also what happened before that, and what things were like when it happened.

So without further adieu,

Note that in this video, I refresh the page after noticing that it has an error. That’s because you get more information from the developer console if it’s open at the time of the error, because it’s hooked into your JavaScript code and recording everything in detail. For this reason, I keep my Developer Tools open most of the time during development.

So you might be wondering: what is the call stack? Well, JavaScript is structured around functions: calling functions and having functions call each other is the fundamental tool to make complicated things in JavaScript.

The hierarchy of what function called which other function is the call stack: a listing of functions from closest to furthest from the currently-running line of code. The call stack is central to debugging because it reveals two fundamental principles:

  • time: what led up to this error: which functions were called
  • scope: the variables currently accessible by a function

Stopping Time

In the ancient past, the standard for debugging JavaScript was to litter code with calls to window.alert(), which would trigger a popup with some value displayed, or just 'hey' if you wanted to check that some portion of code was running.

With the emergence of developer extensions in most browsers, people switched to console.log(), which prints something in your console instead of popping up a window, and if you call it with an object or element or some other kind of complex type, it’ll pretty-print and let you inspect its properties.

Here’s the third wave: breakpoints. Read that as ‘take a break at these points’ instead of ‘make something broken’.

Unlike console.log and alert, breakpoints don’t need to be written into your code. They’re also much better.

console.log logs only the things you choose: usually people will write console.log(foo) or something similar and hope that that’s the important part. Breakpoints, on the other hand, do something much different: they stop time, letting you look at the values of any variable.

There are two ways of setting a breakpoint: the first, and most common, is to set them via your web browser.

Reacting to Failure

Breakpoints are useful, and error details are too: let’s combine the two.

Chrome has a wonderful feature called ‘Break on Exceptions’ that combines the magic of error details and breakpoints - whenever an error occurs, it’ll stop time just like a breakpoint, with the same knowledge of its context.

I keep Break on Exceptions on whenever working on a project under development: it keeps me aware of any problems as soon as possible.

Rule of Repair: When you must fail, fail noisily and as soon as possible.

I like to follow the Rule of Repair from The Basics of Unix Philosophy: it’s much better to fix problems sooner than later.

See how this is the combination of closely inspecting an error and stopping time with breakpoints? Notice that when you’re stopped on a breakpoint, all of the variables in scope at that time are accessible from what you type in the console.

Homework

Once you’re comfortable with the developer tools, some useful things to learn:

-

These aren’t protips: these are essential skills that make the process of learning and understanding JavaScript faster and less painful. Fixing problems without feedback is driving blind: don’t do it if you don’t have to.