JavaScript Debugging

JavaScript Debugging

I thought I would put together some small notes around debugging Javascript in the Browser.

Linters

Yes Linters have nothing to do with the browser, however to discuss JavaScript Debugging in 2019 it is impossible not to start with Linters.

Why Linters?

Well for starters when I started coding for the web there was nothing like linters that existed. This meant that alot of your errors where simple ones that could have been picked up just by a small test of closing brackets and semi colons. So why Linters, well because its 2019 and we are all using some form of an IDE and adding a linter really does help pick up the silly little mistakes that are so easy to make when you are spending hours on lines and lines of code. Linters will help pick up the small mistakes and correct any formatting. So running Linters on our code especially before commencing browser debugging will 100% save time on debugging by knocking out any formatting mistakes early on.

Console

The Javascript console in the browser is a powerful tool and there are is a subset of console functions to enable and facilitate debugging. In the earlier days of JS these functions coupled with alert() was enough to locate the bug. However these days JS is not just being used for form validation and basic DOM manipulation. With JS frameworks and the complexity of modern websites DOM trees debugging JS these days requires being able to combine various debugging techniques to help isolate the problem. Different debugging tools enable us to view the state of our variables (DOM elements) throughout the lifecycle of our application.

Logging lines to console

console.log()

Console Log will print out a variable in the console of the browser, it will print out what the variable is holding at that exact moment in the script. You can use console log at various points in your script to check what the DOM reports as being stored for that variable. This allows you to check the value of a variable after it passes through a method etc.

console.log(hello);

if (x < 3) {
var hello = "Hi";
}

console.log(hello);

Objects as table

console.table()

Console Table will print a complex set of objects in a table view within the console.

var beer = [
    { beer: 'One Way IPA', style: 'India Pale Ale', ibu: 40 },
    { beer: 'ESB', style: 'Ordinary Bitter', ibu: 23 },
    { beer: 'Saison 1858', style: 'Classic Saison', ibu: 58 }
];
 
console.table(beer);

Stack trace for function calls

console.trace()

Another handy Console debugging function is console.trace() can be used in order to find out which event/trigger called a function.

var Beer = function() {
	this.brewer = ‘Tree House Brewing Company’;
        this.style = ‘IPA - Imperial / Double’;
	this.funcX = function() {
		this.funcY();
	}
	this.funcY = function() {
		this.funcZ();
	}
 	this.funcZ = function() {
		console.trace(‘trace beer’)
	}
} 

var beer = new Beer();

Basic loop benchmark

We can perform basic bench mark checks on looping methods by using the console.time function. .

console.time('Timer1');
var items = [];
 
for(var i = 0; i < 100000; i++){
   items.push({index: i});
}
console.timeEnd('Timer1');

Timer1: 26.6962890625ms

Testing assertions

We can use console.assert() to check if our assertions are true or false. The function will take an argument and a message that it will write to the console only if the assertion is false.

console.assert(document.getElementById("beer"), "You have no element with ID 'beer'");

Counting iterations

A good way to check our loop iterations is to use console.count(). We can use this to capture and output the number of times that particular console.count() is called within a loop. We can also use console.count to see how many times a particular element or function is called.

console.count(beer);

for (i = 0; i < 5; i++) {
  console.count();
}

var beer = new Beer();

Debugging Functions

Pausing code execution

When debugger is read it will stop the execution of the script at the location and calls the debugging function. The debugger; statement will function as a breakpoint, pausing code execution, allowing investigation of code in a paused state.

var x = "Hello World";
debugger;

Debug function call

You can use debug(functionName) in the console and in your script. The debug function will cause the script to stop when it reaches the function that was passed in. Using the debug function can be handy as with debugger; you need to know the exact line number where the function you want to debug is. By calling debug() we call direct to the function and do not need to know exactly where it lives in the codebase . Unfortunately the debug function does not work on private and anonymous functions.

debug(beer.funcY);

Typing debug(beer.funcY) in the console and/or in your script will stop the script in debug mode when it gets a function call to beer.funcY

Popup messages

By using the `alert()`function you can create a popup alert that will execute when your code meets a particular condition. This can be a good quick method to check a variable and have it displayed on the screen. As you can gather this is not a good way to debug numerous bugs as you can quickly end up with a series of screen alerts.

var beer = new Beer();
alert(beer);

Web Developer Tools

Both Chrome and Firefox present similar options with small differences, it is a good recommendation to debug in multiple browser platforms, also where possible on OS and device emulation there really is no other way to highlight any cross platform issues (Safari and Edge also have their own). I have just presented a few in this article that I use often and are good to help someone get started in debugging JS in the browser. There are so many options and you can get so deep that it really is best to look at the browsers own “debugging” help pages for their web developer tools if you want to dive deeper into topics like blackboxing JS and advanced options for manipulating DOM elements. Another big thing is getting to know the various tabs presented in web developer tools for browsers. Each browser has slightly different but similar options. Your main three areas will be in Elements, Console and Source however depending on what your debugging Network, Memory and Performance tabs will also be a heavily visited place. There are lots of add-ons for each browser main ones to look at would be JS framework inspectors to help provide a more sane understanding of their specific issues and differences in how they communicate with the DOM.

Screenshot of Chrome JS debugging tool
Chrome JavaScript debugging tool

Key thing to remember is that within the inspector window in all browser platforms web developer tools your options for what you can do with elements are not the same as within the normal browser window space. Of course we also need to mention that any changes made to scripts in the inspector window lives temporarily in the DOM and is not reflected on the final script this is purely a debugging tool.

https://developers.google.com/web/tools/chrome-devtools/javascript/

https://developer.mozilla.org/en-US/docs/Tools/Debugger

Scope, Watch and breakpoints

All browser debuggers allow you to place breakpoints to allow the JavaScript to be paused and display the watched expressions and scope. These are the key areas of JS browser debugging. By adding an expression to watch you are able to see how its scope is changing as it passes through various functions and state changes.

Firefox JavaScript debugger showing onClick() expression watch and scope windows
Firefox debugger showing onClick() expression watch and scope windows

Chrome – Monitoring DOM changes

Chrome allows you pause when a DOM element or its attributes has been modified or removed.

From inside the Chrome Inspector, right click on the element, in the menu you are then presented with break options for the element, you can turn on one or all of them depending on your needs.

Screenshot of Chrome web developer tools in the browser
Screenshot of Chrome web developer tools in the browser and the options menu for elements

Firefox – DOM Inspection

In Firefox browser if you right click on an element in the browser and select inspect element it will take you to take element in the inspector view. If you then right click on that element in the inspector view you have a new set of options. At the bottom of the options is Show DOM Properties. This will print out the full DOM object in the console.

Screenshot of Firefox web developer tools inspector window element menu options
Screenshot of Firefox web developer tools inspector window element menu options

Firefox – Modifying attributes

In the inspector element menu you can easily add or remote attributes on elements. This option will allow you to modify the code presented in the inspector window and display this change on the screen.

Modifying attributes on code presented in inspector window to see it reflected on the screen

Use in Console

The menu also allows you to use a temporary variable of that element to use in the console allowing you to test any needed changes on the element direct in the console before modifying the JS code.

Firefox – State change

Firefox web developer tools make it quite easily modify to force an element int the DOM into a STATE which will then display this on the screen and any expected changes. This enables you to test any expected display outcomes on the screen.

Screenshot of Firefox web developer tools menu options for state change
Firefox web developer tools enables the easy ability to force state change of an element

Firefox – Accessibility

In Firefox web developer tools you can enable “Accessibility Features” this enables a new tab in your inspector that provides details about accessibility features on the page that the DOM has been able to interpret.

From this tool we can see what the element is registering as its childCount and indexInParent. This information assists with debugging on Wai-Aria calls in Javascript applications such as an interactive spreadsheet (Google Sheets) in this situation we need to be able to test the relationship of the cells to ensure the desired workflow is being interpreted by assistive technologies.

Firefox Screenshot of Accessibility options provided in web developer tools
Accessibility features in FireFox enable you to see the Parent/Child relationship of an element