Using JSLint to Refine Your Code
JavaScript is an increasingly popular language thanks to the proliferation of web apps and the adoption of HTML5. Part of JavaScript’s appeal is the ease by which one can begin writing useful and fun stuff with it. There’s no need for heavyweight integrated development environments (IDEs) or third-party apps. Just open any text editor, save the file, and open it in a web browser.
JavaScript’s lure can easily turn into a trap for novice programmers. The malleability of the language can create monstrous bugs in sophisticated scripts. For example, a missing local variable declaration can mysteriously manifest itself elsewhere on the page by altering global variables.

Enter JSLint. According to its website, JSLint is a “JavaScript Code Quality Tool.” Its author, Douglas Crockford, is well known for his work on the development of JavaScript (also known as ECMAScript) and JSON. JSLint helps JavaScript programmers by making sure certain coding conventions are followed. JSLint is based on the premise of strict mode, which is available in the fifth edition of the ECMAScript standard. With strict mode, you are making your code run with a set of more restrictive rules than normal.
Using JSLint
Let’s run through an example usage of JSLint. We are writing a simple jQuery plugin that displays a message specified in the msg
parameter with a prefix. The prefix is hidden if we pass the value false
through the type
parameter.
(function ($) {
$.fn.loading = function(msg, type, cssClass){
var prefixes = {
warning: 'Warning: ' + msg,
error: 'Error: ' + msg,
info: 'Info: ' + msg,
warning: 'Caution: ' + msg,
};
if (type) {
concatMsg = prefixes[type];
} else {
concatMsg = msg;
}
$(this).each(function() {
var tis = $(this)
if (msg == false) {
tis.html('');
} else {
tis.html(concatMsg);
}
});
}
})(jQuery);
Although this piece of code works fine as a plugin for jQuery, when you use it in Firefox or Chrome, you can see that there are some glaring mistakes and some very subtle ones. Instead of spending your mental energy digging out the problems, let’s use JSLint to help us. Copy the function code into the text area on the JSLint site and click the “JSLint” button. Some of the resulting JSLint output is shown in the figure below.

The first error pointed out by JSLint is that the "use strict"
statement is missing. This error indicates that the function is not executed in strict mode. To correct this error, enable strict mode by adding the following string literal to the beginning of the function body.
'use strict';
After enabling strict mode, click the “JSLint” button again. The reported error of the missing "use strict"
should be gone. We can now move on to the next error, shown in the following figure. This error deals with whitespace, and is more cosmetic than functional. Since this is not an actual error, you can safely ignore it.

You can choose to stick with no space after the function
keyword, and suppress the error message by scrolling to the bottom of the page and switching the “messy white space” option to true
. For now, however, we want to keep the default behavior because this option also checks for other whitespace issues as we will see later.
Also notice that the second and third errors reported by JSLint are also on the same line but at different positions. Looks like a space between the closing parenthesis and the opening brace is also recommended by JSLint, so fix that now.
By clicking the “JSLint” button again, we see that the next problem is on line 8, at position 39. The prefixes
object literal contains two identical warning
properties, which is obviously a mistake. Let’s correct the problem by replacing the second occurrence of warning
with caution
.

Without clicking the “JSLint” button again, let’s look at the next error, shown in the following figure. The object literal contains a trailing comma. Browsers such as Chrome and Firefox may be tolerant of such mistakes but Internet Explorer does not take too kindly to such transgressions. To correct the problem, simply remove the comma.

The next two errors indicate that concatMsg
was used before it was defined. When a variable is not defined in the current scope, JavaScript checks the enclosing scopes to see if it was defined elsewhere. If you are using code from a third-party source that happens to define this exact variable in the global scope, it can take you countless, hair-pulling hours to find the bug. Fortunately, with JSLint, we are able to nip the problem in the bud.

While fixing this problem, we can also refactor our code. Since the default value of concatMsg
is msg
, we can assign this value immediately and change it later if need be. The code for concatMsg
can now be rewritten as shown below.
var concatMsg = msg;
if (type) {
concatMsg = prefixes[type];
}
Next, we encounter the same whitespace issue as earlier, which can be corrected in the same way. Next, JSLint reports that a semicolon is missing. This message is shown below. Without the semicolon, JSLint assumes that the statement is never terminated. That is why it saw if
while expecting a semicolon. While the language specification says that the ending semicolon is optional, it is good practice to include it. This is another area where sloppy coding can lead to hard-to-find bugs in large scale productions. By linting our code, we can fix such problems quickly and easily.

The following error is another good one. There are equality and strict equality checks in JavaScript. In our code, by not checking for strict equality the plugin behaves the same if either an empty string or the Boolean value false
is specified as the first parameter. To correct the error, use the strict equality operator.

This is a good time for us to click the “JSLint” button again. The first error, shown below, is reported at line 10. JSLint seems to think that another best practice for writing JavaScript is to group variable declarations together. Although concatMsg
is right after prefixes
, JSLint prefers that you group the variable declarations in a single statement, separated by commas.

The next error is another cosmetic suggestion by JSLint. The fact that there is one more space than the expected number is pretty trivial at first glance. However, indentation problems can lead to bugs that are hard to catch in large scripts. For consistency, move the closing brace back into place by removing the extra space.

The next problem reported by JSLint is similar to what we have seen before, but it is manifested in a different form. JavaScript functions can be assigned to variables. As with any other variable assignment, JSLint expects a terminating semicolon.

Finally, two problems are reported at the last line, as shown below. The first problem is a suggestion to place the closing parentheses after the closing one behind jQuery because it leaves no ambiguity that you want the function definition to be a closure. The second problem is that in JSLint’s view, the variable jQuery is not present, although it might have been included in the web page by linking to a jQuery file. To address this issue, type jQuery
into the bottom text field.

If you run JSLint again, it will detect that the function accepts three parameters. However, in this example, the third parameter is never used. There are two approaches you can take here. The first one is to remove the parameter since it is never used. The second option is to toggle the JSLint property “unused parameters” to true
, as shown below. Choose this option only if you really want to keep the parameter in the function signature for some reason.

After using JSLint to improve our code, the final product is shown below.
(function ($) {
'use strict';
$.fn.loading = function (msg, type, cssClass) {
var prefixes = {
warning: 'Warning: ' + msg,
error: 'Error: ' + msg,
info: 'Info: ' + msg,
caution: 'Caution: ' + msg
}, concatMsg = msg;
if (type) {
concatMsg = prefixes[type];
}
$(this).each(function () {
var tis = $(this);
if (msg === false) {
tis.html('');
} else {
tis.html(concatMsg);
}
});
};
}(jQuery));
JSLint Directives
JSLint directives allow you to define variables and provide other options to JSLint from directly within the source code. This frees you from having to set the JSLint GUI options repeatedly. For example, the comments in the following example define a global variable named jQuery
and set the “unparam” option to true
.
/*global jQuery*/
/*jslint unparam: true */
(function ($) {
‘use strict’;
…
}(jQuery));
Conclusion
In this short example, JSLint has pointed out some critical errors and some seemingly insignificant ones. The fact that JSLint helps us catch these issues before we actually run the code is hugely beneficial in terms of developer productivity and application quality. If you are serious about writing production quality code, always run it through JSLint before pushing it to the server. JSLint is even contained in a single JS file, so you can download it use it offline too!