Debug your site faster with ECMAScript Strict Mode
By Rajasekharan Vengalil
What is strict 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).
Can you spot the bug in the following snippet? With Strict Mode on, the runtime will!
Strict mode contexts
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, “o.name” 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.
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:
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
Training and Certifications
All Developer Centers and Hubs