Why linting Javascript is totally bloody useless

There was a post this week that was talked about how a missing “var” ruined their launch (because it put the Javascript variable in the global/module scope). All of the discussion about this seemed to focus on one thing “You Should Have Run jslint”.

I’m here to tell you that jslint (and the fork: jshint) is absolutely bloody useless, and hence I don’t use it.

Let’s have a quick look shall we. First let’s install jshint (which is better than jslint, and more modern):

$ sudo npm -g install jshint
/usr/local/bin/jshint -> /usr/local/lib/node_modules/jshint/bin/hint
jshint@0.5.2 /usr/local/lib/node_modules/jshint 
├── argsparser@0.0.6
└── minimatch@0.0.4

That all went well… So lets try it on haraka.js:

$ jshint haraka.js 
haraka.js: line 3, col 1, Use the function form of "use strict".
haraka.js: line 5, col 14, 'require' is not defined.
haraka.js: line 8, col 1, 'process' is not defined.
haraka.js: line 8, col 22, 'process' is not defined.
haraka.js: line 10, col 5, 'require' is not defined.
haraka.js: line 10, col 34, 'process' is not defined.
haraka.js: line 13, col 5, 'process' is not defined.
haraka.js: line 13, col 46, 'process' is not defined.
haraka.js: line 16, col 14, 'require' is not defined.
haraka.js: line 17, col 14, 'require' is not defined.
haraka.js: line 18, col 14, 'require' is not defined.
haraka.js: line 20, col 1, 'exports' is not defined.
haraka.js: line 21, col 35, '__dirname' is not defined.
haraka.js: line 24, col 1, 'process' is not defined.
haraka.js: line 34, col 5, 'process' is not defined.
haraka.js: line 37, col 52, 'exports' is not defined.

16 errors

WTF? This script is pretty battle tested. Everything it has complained about are node.js variables, but everything I have read told me that jshint was node.js compatible.

So maybe jshint just shouldn’t be used. Let’s do a search on NPM for alternatives:

lint                  This package provide lint validation library + node-lint command line tool allows you to che

Looks promising. Installed it, tried it:

$ node-lint haraka.js 

        throw e; // process.nextTick error, or 'error' event on first tick
Error: Cannot find module 'vows'
    at Function._resolveFilename (module.js:320:11)
    at Function._load (module.js:266:25)
    at require (module.js:348:19)
    at Object.<anonymous> (/usr/local/lib/node_modules/lint/lib/lint/vows.js:5:12)
    at Module._compile (module.js:404:26)
    at Object..js (module.js:410:10)
    at Module.load (module.js:336:31)
    at Function._load (module.js:297:12)
    at require (module.js:348:19)
    at Object.<anonymous> (/usr/local/lib/node_modules/lint/lib/lint/index.js:15:16)

Fucking useless. And dependencies really aren’t that hard in npm. Let’s press on:

nodelint              The nodelint command line tool allows you to check for problems using JSLint. You can specif

What do we get:

$ nodelint haraka.js 
0 errors

Praise Thor! OK so now we’re getting somewhere. Let’s move on to another file:

$ nodelint utils.js 
utils.js, line 5, character 78: Use the array literal notation [].
var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
utils.js, line 9, character 10: Move 'var' declarations to the top of the function.
for (var i = 0; i < 36; i++) {
utils.js, line 9, character 10: Stopping.  (10% scanned).

3 errors

These kinds of errors are completely fucking unreasonable, and laid down by Crockford who clearly needs to revise his viewpoint – putting the var in the for() statement is a reasonable thing to do, and yes I KNOW it doesn’t do what it looks like it does. I don’t care. And the problem is that these aren’t configurable checks for jslint – the “var at the top of the function” is not a parameter in the jslint config, and if it finds too many of those it just stops until you fix them!

So does nodelint actually find anything worth worrying about?

The truth is, yes it does occasionally find some issues, but getting it to accept your style is hard. Getting it to find real bugs is really hard. I’d love to be proved otherwise.


17 thoughts on “Why linting Javascript is totally bloody useless

  1. In case of JSHint I suppose you use global strict mode (which can be dangerous for client side scripts) and Node global variables. Now, linters are not magic—they can’t magically recognize that you want to use your script in a NodeJS environment so you simply had to set the node and globalstrict options. It would take you less time than writing this angry blog post.


    • All I did was install it via npm. If I’m doing that then I’m using node.js and thus I expect it to just work. Sorry if my expectations are unfair, but that’s how the world works. And no, it would not take me less time than that blog post – where is the documentation for that option?
      $ jshint --help
      Usage: jshint path path2 [options]


      --version display package version
      --config custom config file
      --reporter custom reporter
      --jslint-reporter use a jslint compatible xml reporter
      --show-non-errors show additional data generated by jshint

      • Good point about options docs on –help, thanks. I will let the guy who maintains the NPM package know.

        That said, the statement “I installed it with NPM therefore I use it to check JavaScript in Node environment” is not unfair it is complete nonsense, sorry. I use our NPM package and I use it to automatically test client-side JavaScript before each commit. Other people use NPM package simply because it is the easiest way to check their JavaScript for mistakes and typos. (The other easy way is jshint.com but that requires copying and pasting)

        But I feel like you just want to be angry. Be angry then—bye!

      • Dude, seriously stop saying I’m angry or your comments will be deleted. Frustrated, sure, because linting JavaScript is way over sold as a solution to all problems that don’t show up until runtime.

        But yes I’m sorry if an app that you install by first installing node, and then installing npm, doesn’t by default lint perfectly valid node code, then it is broken. At the very least it should provide a command line flag.

  2. I agree with your thought that these jslint-type programs are useless if they can’t be configured.

    Coming from perl, I love Perl::Critic and perltidy. But perlcritic is super ultra configurable, and therefore it only catches the problems that I really care about. I wish someone with better skills than I would write jscritic.

  3. I find Jslint useful, and I also find very useful this line in nodejs files:
    /*jslint node: true */

    And if you want to use “var” inside the “for” statement, why don’t you use nodejs with harmony flag and the “let” statement instead of the “var” statement?

    • > if you want to use “var” inside the “for” statement, why don’t you use nodejs with harmony flag and the “let” statement

      I write software that other people run. Because there’s no way to set the harmony flag on a per-js file basis, that’s not a feasible option.

  4. This whole thing smells like you want to ride the “NodeJS is cancer” wave. RTFM on JSHint. Here’s my ~/.jshintrc:

    “node” : true,
    “jquery” : true,
    “multistr” : true, // to allow multiline strings (#49)

    // EcmaScript 5.
    // “es5” : true, // Allow EcmaScript 5 syntax.
    “strict” : false // Require `use strict` pragma in every file.
    // “globalstrict” : false, // Allow global “use strict” (also enables ‘strict’).

  5. I have tried and sworn as JSLint in the past. It’s not clean and consise and is OLD. JSHint is much more acceptable to use on current projects. I’m not using it on the build anymore, because of issues that you’ve pointed out. JSHint integration into RubyMine/Intelli J seems much more robust and helpful, so I now rely on that and pay attention when it red flags me. Using strict mode helps, and having tests in javascript should be enough to weed out runtime issues given js is a dynamic language.

  6. Many companies and projects require your JavaScript code to pass JSHint and/or JSLint with no errors or warnings. Just as an example, here are the coding standards for contributing to Ghost…


    IntelliJ, WebStorm, Brackets, and other editors allow you to see JSLint results while you’re working with your code. It’s not considered done until it’s clean.

    One other reason for using them is that it also forces everyone to use the same coding style. Yeah, it may suck if it’s not “your” coding style, but work in a team environment where everyone and his kid brother has his own “style” and you’ll start to realize just how valuable a single coding standard can be.

    Finally, as others have mentioned, both tools can be configured. You just have to spend at least 10 minutes or so browsing the documentation…

    • Please note that this blog post was written a while ago so things may have changed with jshint (though not so much with jslint). Simply put the configurability is (perhaps was?) just not there. These tools will error out on simple things that should be configurable. Take a look at something like perltidy for how it should be done – every single little thing is configurable.

      The other way to go is gofmt, which enforces an even stricter style guide, but at the very least this came from the Go developers, rather than one man’s opinion on what is good style.

  7. Proper .jshintrc would really help you out. I bet most of these options would make your eyes bleed, but it’s what I use. I also use GJSlint

    “asi”: true,
    “laxcomma”: true,
    “node”: true,
    “esnext”: true,
    “bitwise”: true,
    “eqeqeq”: true,
    “immed”: true,
    “indent”: 2,
    “latedef”: true,
    “newcap”: true,
    “noarg”: true,
    “quotmark”: “single”,
    “undef”: true,
    “unused”: true,
    “trailing”: true,
    “smarttabs”: true,
    “strict”: true

    Also GJSLint .gjslintrc


    Those both running simultaneous over your code should give you brain hemorrhoids !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s