Strict Mode in JavaScript

JavaScript strict mode tells the interpreter to be more particular about what is allowed. In general terms, strict mode makes your code a little safer by turning some bad coding practices into exceptions.

For existing code, this is good and bad. It’s good, because it helps you find some potential bugs, like accidental globals. It’s bad because code that used to work, might now be broken.

Here’s the kicker: for new code, it is almost always good.

How To Enable It

This part is easy. Strict mode is enabled by placing the literal string “use strict”; at the top of the scope you want to be strict.

"use strict"; // entire script file is strict mode
undeclaredvar = "value"; // throws exception
undeclaredvar = "value"; // works... not in strict mode
 
function callMe() {
  "use strict"; // only this function is strict
  undeclaredvar2 = "value2"; // throws exception
}
callMe();

That’s it! And the best part, is that it is backwards compatible. In older browsers and interpreters, it degrades to nothing but a literal string. Sure, it won’t enforce strict mode, but it won’t cause any errors, either.

Now let’s take a look at what it does.

Stuff You Don’t Care About

There are a number of things that strict mode does that most people don’t or shouldn’t care about, but it is important to at least know what’s going on.

Removed Support for with Keyword

You shouldn’t be using the with keyword anyway, but in strict mode it is explicitly not allowed.

"use strict";
 
var obj = { which: { has: { really: { deep: { nesting: {
            value: "a val",
            toString: function() { return "value: "+this.value; }
} } } } } };
 
with (obj.which.has.really.deep.nesting) { // throws exception
  info(toString());
  value = "changed!";
}
info(obj.which.has.really.deep.nesting.toString());

Octal Notation Not Supported for Numeric Literals

You are probably not using octal notation either. The main reason this was removed is to avoid confusion over preceding 0’s.

//"use strict"; // uncomment this to enable strict mode
var num = 042;
alert(num); // alerts 34

Stuff You Kinda Care About

Strict mode also provides a number of things that some people care about, but are not particularly important or high-impact.

Future Reserved Keywords

In order to make room for future enhancements to the language, some words that have no function are treated like reserved words. That means they cannot be used as identifiers.

"use strict";
var static = "static is a string!"; // throws exception
 
function private() {
};
 
// complete list:
//implements, interface, let, 
//package, private, protected, 
//public, static and yield

Don’t read too much into this. Just because the standard calls these “future reserved keywords” does not mean these will be added to the language soon, or at all. Don’t hold your breath.

Cannot override eval or arguments

This is another safety measure. Previously, you could override the eval function. “Replace the built-in eval function? What could go wrong with that!” I digress.

With strict mode enabled, “eval” and “arguments” are not allowed identifiers in user code. This means you cannot create a variable or function with the name “eval” or “arguments”. Since I know you love code, here’s a tiny clip.

"use strict";
function eval(code) { // throws exception
  var arguments = []; // throws exception
}

Cannot Use arguments.caller or .callee

The ability to access the current executing function, and the function that called it is potentially useful. The main reason this is not allowed in strict mode is for performance.

One of the optimizations that most interpreters use is to in-line functions when possible. This helps performance by reducing the size of the call stack and even (in some cases) reducing the number of run-time closures. When you reference arguments.caller or arguments.callee, this optimization is no longer possible. Combined with the fact that very few people ever use this functionality, it is disallowed in strict mode.

function FunctionName() {
  alert(arguments.callee.name); // alerts "FunctionName"
}
 
function FunctionName2() {
  "use strict";
  alert(arguments.callee.name); // throws exception
}
 
FunctionName();
FunctionName2();

The Good Stuff

No more suspense. These are the real reasons you should be using strict mode.

Cannot Use Undeclared Variables

No more automatic globals. ‘Nuff Said.

(function(window){
  "use strict";
  undeclaredvar = "value"; // throws exception
})(window);

You can still create global variables (add new member to the global object — “window” in a browser), but strict mode forces you to do it explicitly.

Safer Eval

One of the most dangerous and misused features of JavaScript is the eval function. Any string can be executed as code, and it executes in the context of the call to eval. This can lead to some serious security risks.

Strict mode helps to alleviate some of the risks of using eval with two significant changes to the behavior of eval:

1) no more global context coercion

function alertThisFromEvalLoose() {
  eval("alert(this)"); // alerts "[object Window]" -- the global object
}
function alertThisFromEvalStrict() {
  "use strict";
  eval("alert(this)"); // alerts "undefined"
}
 
alertThisFromEvalLoose();
alertThisFromEvalStrict();

2) cannot instantiate variables in outer scope

function newVarFromEvalLoose() {
  eval("var newvar = 'value';"); // creates variable in outer scope
  alert(newvar); // alerts "value"
}
function newVarFromEvalStrict() {
  "use strict";
  eval("var newvar = 'value';"); // creates variable only within the eval scope
  alert(newvar); // throws exception -- newvar is not defined
}
 
newVarFromEvalLoose();
newVarFromEvalStrict();

Immutable Members Fail Loudly

Property descriptors from ECMAScript 5 gave us the ability to create truly immutable object members. As you work with these, you will surely notice that assigning a non-writable property fails, but fails silently. The only feedback that the assignment failed is the fact that the value didn’t change.

Strict mode causes these assignments to fail loudly. That is, it will throw an exception if you try it.

var obj = {};
Object.defineProperty(obj, "const", { value: "const val", writable: false });
 
function setLoose(val) {
  obj.const = val; // no errors, but does not change the value
}
function setStrict(val) {
  "use strict";
  obj.const = val; // throws exception
}
 
alert("starting value: " + obj.const); // alerts "starting value: const val"
setLoose("new val 1");
alert("modified 1: " + obj.const); // alerts "modified 1: const val"
setStrict("new val 2");
alert("modified 2: " + obj.const); // doesn't get this far because of the runtime exception above

Note that unlike most strict mode messages, this is a run-time exception. You won’t see it until you run the code.

What Does It All Mean?

In its current incarnation, strict mode is a great tool to help prevent some common JavaScript mistakes and the resulting bugs. It is supported in all modern browsers (yes, even IE), and it degrades gracefully to older browsers without any extra work.

In short… you should be using strict mode in nearly all of your JavaScript code. Do it! Do it now!

One Response to “Strict Mode in JavaScript”

Leave a Reply