Software Development Magazine - Project Management, Programming, Software Testing |
Scrum Expert - Articles, tools, videos, news and other resources on Agile, Scrum and Kanban |
JSHint - a JavaScript Code Quality Tool
Anton Kovalyov, Mozilla
JSHint is a static analysis tool written in JavaScript that helps developers detect potential bugs in their JavaScript code and enforce their development team's JavaScript coding conventions. JSHint scans your program's source code and reports about commonly made mistakes and potential bugs. The potential problem could be a syntax error, a bug due to implicit type conversion, a leaking variable, or any of the other 150+ problems that JSHint looks for.
JSHint is flexible enough so you can adjust it to your particular coding style. This flexibility doesn't prevent JSHint from spotting many mistakes and potential problems in your code before you deploy them live.
Since JSHint is written in JavaScript, it can be used as a web application, command-line tool or a Node.JS module.
Web Site: https://jshint.com/
Version Tested: JSHint 0.9.1 (r12)
System Requirements: Any environment that can run modern JavaScript (ES5): browsers, Node.JS, Rhino, Windows Script Host and so on.
License and Pricing: Open Source
Support: Project page on GitHub (https://github.com/jshint/jshint/)
and user mailing list (http://groups.google.com/group/jshint).
Why do we need static code analysis tools?
Any code base eventually becomes huge at some point, and simple mistakes - that would not show themselves when written - can become showstoppers and waste hours of debugging. This problem is particularly severe in JavaScript since its rushed development (JavaScript was created under an extremely tight deadline. Brendan Eich - a developer at Netscape - had only ten days to write the language) allowed for quite a few pitfalls to creep into the language. For example, consider the following snippet:
function add(x, y) {
return
x + y;
}
add(1, 2);
A programmer familiar with any other C-like language will probably expect the result of this expression to be 3 and will be very surprised to learn that the actual result here is undefined. This happens because the rules behind statement termination are not as simple in JavaScript as they should be. In this case, your JavaScript engine will automatically insert a semicolon after return because it thinks that return and x + y are two separate statements. So, basically, your JavaScript engine sees your program like this:
function add(x, y) {
return;
x + y;
}
Another common source of bugs is browser incompatibility. Most web developers use only modern browsers so it's easy for them to unknowingly introduce a bug like the one that's in this code snippet:
var episodes = [
"An Unearthly Child",
"Blink",
"Angels Take Manhattan",
];
This code is a perfectly valid JavaScript according to the ECMAScript 5 (ECMAScript is a formalized version of JavaScript. There were a few reasons behind its name and why is it different from JavaScript but they are irrelevant for this discussion. All our readers need to know right now is that ECMAScript 5 is the latest standard for the JavaScript programming language.) specification and it will work just fine in all modern browsers. However, legacy browsers - such as Internet Explorer 6 or 7 - will fail to parse a trailing comma before the ending bracket and throw a syntax error. And unless you run all your tests in all supported browsers, this bug will most likely slip through the cracks and into the production. There is at least one case of a startup whose launch was almost ruined by this bug!
This is just a couple examples out of dozens different pitfalls that await anyone who is doing any kind of serious JavaScript development. This is where static code analysis tools come into play and help developers to spot these and similar problems. But before we dive into more examples, let's look at how to install and configure JSHint.
Installation
The simplest way to use JSHint is through your browser. Just go to http://jshint.com/, paste your JavaScript code and press Lint. JSHint will scan your code and generate a report on the same page.
Using the website works well for smaller chunks of code but it becomes increasingly annoying to be constantly copying and pasting your code. In addition to that, it's impossible to automate your "linting" process and integrate JSHint into your development workflow through the website.
That's why we have a command-line version of JSHint, distributed as a Node.JS module. Assuming that you already have Node.JS installed all you need to do is run the following command:
$ npm install jshint -g
Once it finishes installing the package you will have a jshint program available to you:
$ jshint myfile.js<
myfile.js: line 2, col 9, Missing semicolon.
myfile.js: line 5, col 6, Extra comma.
If you point JSHint at a directory it will scan and check all JavaScript files inside of it.
The JSHint website and our Node.JS package are not the only ways to use JSHint. You can also use JSHint as a plugin for your editor to lint your code while typing. Check out http://jshint.com/platforms/ to see if there's already a plugin for your favorite editor/IDE, and if not, consider writing a plugin yourself.
Configuration
JavaScript is a flexible language, and there isn't one set of coding conventions that everyone follows. For that reason, JSHint is highly configurable, so that you can enable or disable options to suit you and your team's needs. For example, if you want JSHint to report about any variable that was declared but never used you will need to enable the unused option. If you want to make sure that all your code always runs in strict mode, you will need to enable the strict option.
There are two ways to set JSHint options: you can either create a configuration file or use special JavaScript comments. Let's start with a configuration file.
Before JSHint starts parsing your files it looks for a special file named .jshintrc. First, it looks in the current working directory and then goes all the way up until it finds the file or hits the root. Then, if the file hasn't been found yet, JSHint looks for it in your home directory.
The structure of .jshintrc is simple: it is a JSON file with option names as keys. For example, the following file will enable two options: strict and unused.
$ cat ~/.jshintrc
{
"strict": true,
"unused": true
}
Some options, such as undef, need to know whether you're using global variables defined somewhere outside of the current file. The globals can be provided to JSHint via the special globals option in the configuration file. For example, the following snippet will tell JSHint that, in addition to built-in JavaScript globals, you're also using a global variable named MyLib. And because its value is false JSHint will warn if you try to overwrite it in your file.
$ cat ~/.jshintrc
{
"strict": true,
"unused": true.
"globals": {
"MyLib": false
}
}
Sometimes, however, you might want to set options per-file. For example, let's say you have a legacy file that doesn't adhere to your project guidelines but you still want to lint it. You can either extract this file into a separate directory and create a specialized .jshintrc next to it or you can use special comments to configure JSHint just for this file:
/*jshint expr: true, newcap: false */
/*global MyLegacyLib: false */
As you can see there are two type of JSHint comments. The first one, /*jshint, allows you to set options just like we did above in the .jshintrc file. And the second one, /*global, allows you to tell JSHint about a global variable MyLegacyLib.
And this is how you can configure JSHint to your own taste. You can find a complete list of options, together with short descriptions, on http://jshint.com/docs.
Leaking variables
Now that we know how to install and configure JSHint, let's go over a simple usage example. This example was simplified to not to bore you with long code listings but imagine that it is a part of a file with 1000 lines of code.
$.post("ajax/test", function (data) {
var height = 0;
var parsed = JSON.parse(data);
if (parsed.height) {
heigth = parsed.height;
}
changeHeight(height);
});
The code above has a rather small typo that can lead to very nasty bugs. On line 6 we accidentally misspelled height as heigth and by doing so we created a new variable heigth. Because that assignment didn't start with var, JavaScript puts that new variable in the global scope, and we've now leaked what was meant to be a harmless local variable. This example is simple but in a big enough project, such leaks can result in either unexpected behavior or increasing memory consumption of your application. Fortunately, JSHint was designed to catch such mistakes.
We will start by enabling an option undef which tells JSHint to check for variables that were used but never defined. Adding the following line to the beginning of the file will do the trick:
/*jshint undef:true */
Now if you run JSHint over your file it'll produce two warnings:
myfile.js: line 1, col 1, '$' is not defined.
myfile.js: line 6, col 9, 'heigth' is not defined.
An astute reader can tell that only one of these warnings is valid. Variable $ might not be defined in this file but it is defined elsewhere in our project so let's inform JSHint about that by adding another comment:
/*global $:false */
Now we have only one warning and it is about heigth being undefined. We found our leak, can very easily fix it and verify the fix by running JSHint over that file again.
Summary
Now you know how to install and configure JSHint. You also learned how to use the tool to find leaking variables. But finding leaks is just one possible use of JSHint - and there are many more. Go over our documentation and find out how JSHint can help you in spending less time looking for missed semicolons and forgotten var keywords, and more time writing code.
Also, JSHint is written in JavaScript so it can be used almost anywhere. It comes with a safe set of default options so more novice programmers don't have to start by configuring it. And more experienced programmers can fine-tune JSHint to their own taste.
Documentation and Literature
The general documentation of JSHint is available on the project homepage: https://jshint.com/. And if you want to use JSHint as a JavaScript module, more technical documentation is available on the projects GitHub page: https://github.com/jshint/jshint/.
There is also a great book "Maintainable JavaScript" by Nicholas Zakas that teaches how to write maintainable code and use tools such as JSHint to keep your team on track: http://shop.oreilly.com/product/0636920025245.do
More Code Analysis and Software Testing Resources
Open Source JavaScript Code Analysis
Software Testing Videos and Tutorials
JavaScript Tutorials and Videos
Click here to view the complete list of tools reviews
This article was originally published in the Winter 2012 issue of Methods & Tools
Methods & Tools Testmatick.com Software Testing Magazine The Scrum Expert |