Strictly Speaking Javascript

There used to be a string of jokes about how to shoot yourself in the foot in various different languages. For some reason, looking back on what I find in an internet search they aren't nearly as funny as they seemed to be back when I was first learning C, Fortran and Pascal. (I'm sure I haven't changed, it must be that the jokes have molded over time :-). Nevertheless the underlying message remains: in any given language shooting yourself in the foot is either too easy or too hard. If I were to hazard a guess, I think for Javascript the best way to put it might be "You shoot yourself in the foot, but don't notice until you try to stand up".

Javascript's origins and original uses are such that it is a very forgiving language. You can start using variables without declaring them, and you can make a lot of mistakes without anything crashing. But, to coin a phrase, "all things are permissible but not all things are profitable", or to put it another way, "Just because you can do a thing doesn't mean you should". This is rarely more true than it is in Javascript coding.

Yes, you can do things like assign a value to the variable "window" (I just crashed my browser trying that one), or create new global variables deep in the depths of a nest of functions, or give two of your formal parameters the same name or rewrite the arguments list, or abuse eval() or any number of other sins. But this flexibility comes at a price of confusion and headaches when it comes to debugging and maintainance, even when you're trying to be good.

A classic example is the ease with which you can create a variable. Unlike more static languages, you don't need to declare it at all. You don't need to give it a type or anything. You just assign something to it and off you go:

x = 1  // Now x is a variable initialized to 1

Since you haven't declared the variable, Javascript makes a simple assumption, that you wanted x to be a global variable in your program. Now this is all fine and good if that's what you wanted, but most of the time that's not what you want (or at least it shouldn't be).

So, suppose you're a well behaved programmer and you always use local vars unless you really really need a global. You generally declare your vars this way:

var foobar = 0 // foobar is a local variable initialized to 0

So all is well and you shouldn't have any trouble with globals or anything like that. But suppose that, like me, you like to create code with a simple text editor and are prone to typos. You might just make a mistake like this:

fobar = foobar + 1

Of course, you meant to type foobar on the left hand side of the assignment, but Javascript doesn't know that. It will merrily treat this as a newly created global variable, while not updating foobar at all.

When it comes time to debug this problem, you may be left with a feeling that you're being punished for something you didn't mean to do. Now is when you might call into question Brendan Eich's decision to allow new variables to be created without a clear declaration, but alas that ship has sailed and cannot change course without hitting an iceberg and sinking into the cold blue ocean of existing javascript code. Introducing an incompatible change like that to Javascript at this point would break any number of existing websites and apps that it would most certainly be rejected by the vast majority of developers. What to do?

Fortunately there is a way to improve the situation. In EcmaScript version 5, "Strict Mode" was introduced to deal with exactly this kind of problem. The idea is simple. If you don't indicate that you are running in Strict Mode, then the Javascript interpreter will act as it always has, allowing bad habits to go unpunished; "let the coder beware". However, if Strict Mode is indicated, then the interpreter becomes instantly more particular, rejecting undeclared variable assignments, duplicate parameters and object field names, and certain other habits that have come to be considered unhealthy, after some years of experience:

"use strict";
x = 1  // ReferenceError: x is not defined

When this code executes, the interpreter will throw a "RefenceError" with the message "x is not defined". Instead of having a subtle runtime bug to find, you have a simple immediate failure that is already nailed down for you.

Going into Strict Mode is easy, and ironically takes advantage of Javascripts forgiving nature. You simply include the following line at the beginning of your code:

"use strict";

It has to look pretty much exactly like that, though you can use single quotes instead of double quotes if you prefer, it's just a string. Now, when I say, "the beginning of your code" I'm being slightly ambiguous, but Javascript is fairly precise on this point. It must be the first Javascript statement in your code, not including blank lines or comment lines. Specifically though, that means that if you put this at the beginning of a .js file, it will apply to the entire file. If you put it at the beginning of a script tag it will apply to all the code in that tag. If you insert it at the beginning of a function, it will apply to the entire function. If, in any of these cases, you put some other javascript code before it appears (other than white space and comments), then it will have no effect.

This is almost always safe to use. In environments that do not support Strict Mode (like really old browsers) they'll just see a string that is not assigned, essentially a null statement that can be ignored. Any code that works in Strict Mode will work the same way in normal mode, so no problems there. There is one caveat, however. Normally it's almost always safe to cat javascript files together into one big .js file, whether for file compaction or as part of a build system, using Strict Mode can break that. If the first file included has "use strict"; but there is code in other files that are not meant to be used in Strict Mode, when they're combined together the entire resulting file will be executed in Strict Mode.

There are a few solutions to this issue, should it arise. You could refrain from putting "use strict"; at the top of your file and instead include it in each function you write. This would work around the "catting" problem (assuming you don't split functions across files, which would undoubtedly irritate your friends and neighbors.). Perhaps a better solution though, if it is within your power, is to simply write all of your code with the expectation that it will be executed in Strict Mode. Failing that, you could wrap your entire file in a Strict Mode function, then execute it immediately (IIFE). Either way, you'll thank yourself later.

If you want to see more details about exactly what Strict Mode does you can check out the MDN page on the subject.

Para obter informações mais completas sobre otimizações do compilador, consulte nosso aviso de otimização.