Debug your site faster with ECMAScript Strict Mode

By Rajasekharan Vengalil

ECMAScript, ratified for widespread adoption by Ecma International, is standardese for what much of the world knows as JavaScript.

Strictly speaking (no pun on title intended), JavaScript and ECMAScript aren’t identical. JavaScript is a dialect of ECMAScript, but the differences are mostly negligible and largely exist for historical backward-compatibility reasons. ECMAScript 5, the latest version available, (henceforth referred to as ES5) brings a suite of interesting features to the table. Most of these new features are designed to bring greater programming discipline to the language.

I’m going to focus on Strict Mode—one of the features that directly addresses some of the more notorious parts of the language. Essentially, it’s an entirely new execution mode for JavaScript that causes the execution engine to run code with slightly different semantics.

What is strict mode?

Strict Mode is a way to cause the runtime engine to interpret and execute JavaScript with different semantics than what you’d see with unrestricted code. Code running in strict mode has the following characteristics:

  1. Excludes some syntactic and semantic features;you can’t do some things that you are allowed to do otherwise.
  2. Modifies semantics of some features;the same code runs differently in strict mode than in unrestricted mode.
  3. Throws more errors in some scenarios; scenarios that that would otherwise be silently ignored or run with assumed intent in unrestricted mode.

Applies to specific code units. You cannot apply Strict Mode to all your .js files in one shot (unless you concatenate all of them, in which case it’s one code unit as far as the runtime is concerned).

The basic rationale behind Strict Mode is the introduction of some runtime-enforced discipline to JavaScript development. I have always felt that JavaScript is far too dynamic for its own good, and, in my opinion, strict mode addresses some of that excessive dynamism.

When you mark a code segment as “strict,” Many of the tricky parts of JavaScript are enforced by the engine instead of requiring programmer discipline.

Can you spot the bug in the following snippet? With Strict Mode on, the runtime will!

Browser support

Pretty much all of today’s modern browsers support Strict Mode in their JavaScript engines, including Internet Explorer, Chrome, Firefox, Safari, and Opera. On Internet Explorer (IE), Strict Mode is available from version 10 onward. You can download the latest platform preview of IE10 from IE Test Drive.

All the samples in this article have been tested on IE10 platform preview using a JavaScript eval console I had put together a while ago. Selected samples have been tested on Chrome 14 and Firefox 7 Beta as well.

Strict mode contexts

Running a piece of JavaScript under Strict Mode is simplicity itself. Here’s an example:

The nice thing is that this is perfectly valid ECMAScript 3 code as well. (ES3 is the previous edition of ECMAScript. What happened to ES4? It went the way of the dodo!) An ES3 JavaScript engine will simply ignore the noop line and proceed with running the rest of the script. In fact, this sort of syntactic backward compatibility with ES3 has been a key design goal for ES5. A surprisingly large part of the ES5 specification can be implemented completely in ES3 JavaScript.

Strict Mode, however, is an example of an ES5 feature that perhaps cannot be implemented purely in ES3 JavaScript without additional support from the runtime.

The following kinds of JavaScript code can be made to run under Strict Mode:

1. Global code

This is basically executable code that you enter inside a script tag. For example:

Note that with HTML5, you no longer need to add the type attribute for script tags.

2. Eval code

Eval code that has the Strict Mode directive prefix:

Or is invoked from strict mode code:

3. Function code

Functions that have the Strict Mode directive prefixed before the rest of the code (putting the directive anywhere else doesn’t count):

Functions declared in Strict Mode code inherit the strictness:

Note that the latter case is particularly relevant when you are defining callbacks for various event handlers.

You should also note that strictness does not extend across call stacks. Here’s an example:

Strict mode restrictions

So what exactly are the restrictions and alternate semantics that apply in strict mode? Let’s review some of the key restrictions:

1. Identifiers must be declared before they can be assigned to

This aspect, in my opinion,makes Strict Modeworthwhile all on its own,even if there were nothing more to it. Undeclared variable assignments do not automatically get added as expando properties on the global object.

With this in place, the following snippet that I’d given above under the “What is strict mode?” section will fail to run and throw a “ReferenceError” instead because of the typo in the variable name “product” in the assignment inside the “for” loop.

2. No automatic context for context-less function calls

Functions that are called without setting an explicit context do not automatically get the “global object” in “this”. Consider the following snippet:

Here, “foo” is being invoked without setting an explicit context object, i.e., we are not calling it like this:

In unrestricted mode this causes the context to be automatically initialized to the “global” object, which in browsers is the “window” object. Since the snippet above was running in unrestricted mode, the expression “this === window” evaluates to true. If we modify the function like so, however, we see that “this” is no longer equal to “window”:

3. Reserved keywords cannot be identifier names

Naming variables and functions as eval, arguments, implements, let, private, public, yield, interface, package, protected, and static will cause errors.

4. Violations of ES5 property configuration cause errors

Violations of the configuration as specified in the property descriptor for ES5 properties will cause errors to be thrown in Strict Mode instead of being silently ignored. Here are some examples:

1. Writing to a non-writable property:

Note the line highlighted in bold. Setting the “writable” property descriptor to “false” makes the “name” property of the “person” object read-only. Attempts to assign to this property will be silently ignored in unrestricted mode but causes a “TypeError” to be thrown in Strict Mode.

2. Changing configuration of a non-configurable property:

Here we attempted to change the property descriptor on a non-configurable object. Again, an error that would have gone unnoticed in unrestricted mode results in a “TypeError” being thrown in Strict Mode.

5. Writing to read-only accessor properties

Writing to accessor properties that do not have a “setter” defined causes errors to be thrown instead of being silently ignored:

Here, “name” is an accessor property that does not have a “setter” method defined. Attempts to assign a value to this property results in an error in Strict Mode while being quietly ignored in unrestricted mode.

6. Cannot extend non-extensible objects

Extending a non-extensible object throws an error in Strict Mode instead of being silently ignored:

7. Other sundry restrictions

There are a few other restrictions for Strict Mode code that are used somewhat less frequently.

Numeric constants are no longer interpreted as having an octal base if you put a leading zero.

Variable/function instantiations in Strict Mode “eval” code occur in an environment that is local to the “eval” code and not in the environment of the calling code. This means that “eval” code cannot introduce new identifiers in the caller’s execution context/scope.

“arguments” is immutable. You cannot arbitrarily extend the “arguments” object by tacking on your own properties to it. Now, why anyone would even want to do this is puzzling to me, but it must have been happening often enough for Ecma to make the effort to specify that you can’t do it in Strict Mode!

“arguments.callee” and “arguments.caller” are not available in strict functions. I have to say, I’m not thrilled with this particular restriction!

Creating duplicate property definitions on an object is not allowed in strict mode code. The following snippet, for instance, produces an error in Strict Mode:

This code throws up a “SyntaxError” with the message, “Multiple definitions of a property not allowed in strict mode”. In unrestricted mode, “” would have the value “bar”.

Calling “delete” on an ES5 property that has its “configurable” property set to “false” results in an error being thrown in Strict Mode. This is a variation on the restriction discussed in point 4 above.

The JavaScript “with” statement is not allowed in strict mode code.

It is not allowed to create functions with duplicate parameter names in strict mode. Again, it defies logic as to why anyone would want to do this, but there it is!

Tips and best practices

Here are a few things you should consider while writing code that uses Strict Mode:

  1. Since Strict Mode is a fairly recent phenomenon, chances are high that some visitors to your web app are running a JS engine that does not understand Strict Mode. (Unless all your users conscientiously update their browsers to the latest version right away. Which I promise, they aren’t, my friend.) This basically means that all your code will run in unrestricted mode, whether or not you’ve used the Strict Mode directive. It’simportant to always test your code in unrestricted mode and make sure everything is still peachy.

Now, even if a major chunk of your end users are on browsers that don’t support Strict Mode, it still makes sense to use Strict Mode in your development environment because Strict Mode helps enforce JavaScript development best practices. At the very least, take advantage of automated enforcement when you develop! And of course, be sure that you test everything in unrestricted mode before going live.

Enable strict mode in small increments instead of a one-shot quick fix. If you have a 3000-line JS file for instance, it’s probably not smart to simply add the "use strict"; directive at the top of the file—semantic differences between the two modes can potentially result in subtle unforeseen bugs. Do it in smaller chunks at a function level, and certainly use it with abandon for new code that you write.

I encourage you to experiment with and read up on Strict Mode. In my opinion, this is one of the best features introduced as part of ES5. I think you’ll find the following resources incredibly useful:

About the Author

Rajasekharan Vengalil has been coding for more than 9 years and works as a Developer Evangelist at Microsoft. He has worked on a wide range of Microsoft products & technologies ranging from VC++, MFC and Win32 programming to the latest developments on the web front, JavaScript and .NET. His current focus is on advances in web development, HTML5 and building rich internet applications.  Read his Nerdworks Blogorama here.