mjl blog
February 17th 2016

Use the function form of "use strict"

If you’ve done any JavaScript development, you’ve probably used jshint. It’s invaluable in pointing out all the weird stuff in JavaScript that you’re about to shoot yourself in the foot with.

Also, you should really “use strict”. This is a statement/expression that signals to newer JavaScript interpreters that you would like some more strict (actually, “less careless”) handling of your code. You can put it at the top of your JavaScript file. Or at the start of a function. Of course, you want all of your code to be checked for sanity! So you do something like this:

$ cat test.js
'use strict';
var run = function() {
    url = 'http://localhost';
};

Oops! We created a global variable “url”. Good thing we have jshint to point this out to us:

$ jshint test.js
test.js: line 1, col 1, Use the function form of "use strict".
test.js: line 3, col 5, 'url' is not defined.

This is where the annoying part comes in.

By default, jshint will complain if you “use strict” at the top of your file. It wants you to specify strictness at the start of your JavaScript functions. The reasoning is that you might concatenate all your JavaScript files. That might cause you to unexpectedly enable strictness for all other conglomerated JavaScripts too. The other files might not all work in strict mode, resulting in a broken web app.

OK, we can solve this. We’ll just put a function call around our entire JavaScript file. This is good and common practice anyway, to prevent carelessly creating global variables:

$ cat test2.js
(function() {
'use strict';

var run = function() {
    url = 'http://localhost';
};

})();

Solved! Right? Let’s run jshint again.

$ jshint test2.js
$

Huh!? No output? That means our code doesn’t have any bad smells. But we can still see that global “url” variable staring us in the face!

Well, it’s complicated. More so than I initially thought. As I was writing this blog post, I had deducted that the “use strict” for the outer function does not mark the inner function “run” as strict. I thought it was going without testing. And that would’ve been very bad and unexpected “use strict”-behaviour. So I added a “use strict” to the body of function “run” and ran jshint again. Just to show that that would start showing warnings again. Let’s try it.

$ cat test3.js
(function() {
'use strict';

var run = function() {
    'use strict';
    url = 'http://localhost';
};

})();
$ jshint test3.js
test3.js: line 5, col 5, Unnecessary directive "use strict".

Hmm, look at the warning from jshint. It seems “use strict” doesn’t have to be repeated in inner functions.

But wait a minute! Where did that warning about “url” not being defined go to? Must be some kind of strange JavaScript behaviour that makes this valid… Let’s experiment to figure out if “url” became a global variable:

$ cat test4.js
(function() {
'use strict';

var run = function() {
    url = 'http://localhost';
};

run();
console.log('url inside', url);

})();

console.log('url outside/global', url);
$ jshint test4.js
$

Fine, so jshint thinks this is valid. I admit I’m properly confused. Let’s run it, and see what real interpreters think.

$ node test4.js
test4.js:5
    url = 'http://localhost';
        ^
ReferenceError: url is not defined

Hah, nodejs says no.

url is not defined

And Chrome also says no. So the JavaScript is definitely incorrect. Jshint should warn about it. We’ve already seen in the first example it knows how to do that.

The lesson from this endeavour? Not sure yet. Please enlighten me. I have some options:

  • jshint is stale and people are not using it. What are people using?
  • “use strict” has even weirder semantics than I initially thought. But… what are they?
  • jshint has a bug.
  • Everyone (but me) knows you should ignore the “use the function form of use strict”-warning from stock jshint and are using file-global “use strict” statements. This is actually what I’ve been doing for a while!
  • I made a silly mistake in my tests, or I have mistaken assumptions. Unfortunately, this is usually what it comes down to when tracking down problems like these. But please, be kind, and point out to me what’s obvious to you!

For reference, “jshint -v” yields “jshint v2.8.0” and was freshly installed today through npm.

Comments

dasf
asd
mjl
You would expect "undef" to be the default. It is with the per-file "use strict". I've been using the per-file "use strict" lately, with a header saying:


/* jshint -W097 */ // don't warn about "use strict"
Ace
Try http://jshint.com/docs/options/#undef, a good example file with credits to AirBnB: https://github.com/airbnb/javascript/blob/master/linters/.jshintrc
Ace
I am facing the same confusing issue with the function form of strict