Note: many of these tips are written with Chrome in mind, but are applicable to any modern browser with developer tools.

1. Understand what is happening in your code

A prerequisite to debugging is understanding the code in question. Before debugging, you should be able to answer: what is the purpose of this function? What should the parameters be? How will this line affect local and global variables?

Basically, run the code mentally before trying to debug.

2. Set and use Breakpoints

Once you understand how the code should function, set execution breakpoints at key places. When reached, a breakpoint will pause the execution of script on that line. You can then “step-through” the code one line at a time. This view also allows you to inspect any global or local values to ensure they are what you expect them to be. Often times, you can observe a variable which should contain a value, but is undefined. From there it is easy to trace your way back up and see where the error is occurring.

Breakpoints can be set by clicking on the line-number in the script tab of chrome developer tools, or programmatically using the debugger; directive.

Use the console api

While sprinkling a few console.log ‘s sparingly throughout your code can be useful, the console api has many useful functions that might serve the purpose better. Here are a few console api methods I have found useful:

console.dir

Displays all the properties of an object.

console.table

Formats arrays and objects as tables, and allows sorting on columns.



console.time

Starts and stops a timer (string tag based), logs time (in ms) of intermediate code.



console.memory

Returns heap information for this process.



console.trace

Returns a stack trace for the function where it is called.

4. De-minify

When debugging, it can be very frustrating to see an error like:

undefined is not a function on line 1, column 400 of library.min.js 1 undefined is not a function on line 1 , column 400 of library . min . js

When at all possible, swap out the minified version for a full expanded and commented version of the script.

When a full version is not available, Chrome’s developer tools come to the rescue. The curly brace button below the script will automatically expand lines for better breakpointing and debugging. It does not however rename obfuscated variable names.



Minification bugs

Every so often, you can run into the maddening bug of a full script working, and the same minified script breaking. Luckily, these bugs often attributable to one of a few small problems (mostly having to do with missing semicolons).

For example:

//Expanded return a + b; //Minified return a+b; 1 2 3 4 5 6 //Expanded return a + b ; //Minified return a + b ;

//expanded a = b + c (d + e).foo() //minified a = b + c(d + e).foo() 1 2 3 4 5 6 //expanded a = b + c ( d + e ) . foo ( ) //minified a = b + c ( d + e ) . foo ( )

These bugs can also creep in from preceding scripts, or when multiple scripts are concatenated together. This is the reason that jQuery plugins typically start with a ; . It is a preventative measure against misbehaving code above it.

;(function(){ /* something in here */ })(); 1 ; ( function ( ) { /* something in here */ } ) ( ) ;

5. Modify scripts locally

Chrome allows you to modify script files and run them locally. Simply double click into source file, type, and CTRL-S to save. Not much more to explain, but very useful trick!

6. Use a Unit Testing framework

There are a handful of very good third-party unit-testing frameworks for JavaScript, each with their own philosophy and syntax.

See this great Stack Overflow post for many more.