Skip to content

Instantly share code, notes, and snippets.

@gkatsev
Last active December 12, 2015 00:39
Show Gist options
  • Save gkatsev/4685345 to your computer and use it in GitHub Desktop.
Save gkatsev/4685345 to your computer and use it in GitHub Desktop.
An overview and features of strict mode

Strict Mode

Overview

Strict mode is an opt-in mode for JavaScript that fixes, disables, and changes some of the most problematic features in the language.

Strict mode is invoked with "use strict"; statement at the top of the current scope. So, it works both in functions and in files. It is better to only ever specifiy strict mode inside of functions because this simplifies concatenating files and bleeding strict mode into functions that were not written with it in mind.

Strict mode functions can call non-strict mode, or sloppy mode, functions. The reverse, of course, applies as well.

You can see the strict mode support in the various browsers via kangax's or croll's strict mode tests.

Note: Seems like v8 is currently not throwing syntax errors in strict mode when using a console.

A Word of Caution

Strict mode helps with the development because it turns a lot of erroneous programming errors into early errors. This is very useful; however, strict mode also changes some semantics that can have code act slightly differently when running via strict mode or sloppy mode.

For example, the value of this changes in strict mode. So, the following function will act differently when it runs in strict mode or sloppy mode.

function add(a, b) {
    var val = this.val || 0;
    a = a || 0;
    b = b || 0;
    return val + a + b;
}

add(1, 2);
// sloppy mode: 3
// strict mode: "TypeError: Cannot read property 'val' of undefined"

Strict Mode Features

  • Assignments that accidentally create global variables will now throw
"use strict";
foo = 5;
// ReferenceError thrown
  • Assignment which would fail silently now throws
"use strict";

// Assignment to a non-writable property
var o = {};
Object.defineProperty(o, "x", { value: 42, writable: false });
o.x = 9;
// TypeError thrown

// Assignment to a getter-only property
o = { get x() { return 42; } };
obj2.x = 5;
// TypeError thrown

// Assignment to a new property on a non-extensible object
Object.preventExtensions(o);
o.foo = "bar";
// TypeError thrown
  • Can't delete undeletable properties
"use strict";
delete Object.prototype
// TypeError thrown
  • Duplicate properties throw
"use strict";
({x: 1, x:1})
// SyntaxError thrown
  • no duplicate function argument names
"use strict";
function sum(a, a, c) {
    return a + b + c;
}
// SyntaxError thrown
  • Octal numbers are forbidden
"use strict";
var num31 = 031;
// SyntaxError thrown
  • prohibit usage of with
"use strict";
var o = {};
var x = 5;
with (o) {
    x = 10;
}
// SyntaxError thrown
  • eval runs code in strict mode as well
function runStrict () {
    "use strict";
    eval("delete Object.prototype");
    // TypeError thrown
}

function run(){
    eval("delete Object.prototype");
}

runStrict();
run();
function runStrict () {
    "use strict";
    eval("var x = 10;");
    return x;
    // ReferenceError thrown
}

function run () {
    eval("var x = 10;");
    return x;
}

runStrict();
run() == 10;
  • Deleting plain names is forbidden
"use strict";
var x = 5;
delete x;
// SyntaxError thrown
  • eval and arguments cannot be bound or assigned
"use strict";
var eval = 5;
// SyntaxError thrown
var arguments = 5;
// SyntaxError thrown
  • arguments no longer tracks changes to the formal name and stores the original value passed into the funciton
"use strict";
function foo (a) {
    a = "foo";
    return [a, arguments[0]];
}
var f = foo(5);
f[0] == "foo";
f[1] == 5;
  • arguments.callee and arguments.caller are no longer available
"use strict";
function foo (calleep) {
    var prop = calleep ? "callee" : "caller";
    return arguments[prop];
}
foo(true);
// TypeError thrown
foo(false);
// TypeError thrown
  • this isn't boxed into an object. Primitives aren't converted to their wrapper objects. Also, calling a function from the global scope, which usually has the function get the global object as the value of this is no longer the case. Instead, this would be undefined.
"use strict";

function foo() { return this; }

foo() === undefined
foo.call(1) === 1
foo.call("foo") === "foo"
foo.call(Number) === Number
  • arguments and caller are no longer available on the function object
"use strict";
function foo () {
    // TypeError thrown
    return [ foo.caller, foo.arguments ];
}
function bar () {
    return foo();
}
var baz = bar();
  • Add some reserved words.
    • implements
    • interface
    • let
    • package
    • private
    • protected
    • public
    • static
    • yield
"use strict";

var implements;
var interface;
var let;
var package;

function protected (public) {  }

static: while (1) {
    var yield;
    break static;
}

// All throw SyntaxErrors
  • no function statements inside of block statements. Functions are only allowed at top level of functions.
"use strict";

if (true) {
    function foo () {  }
    foo();
}
// SyntaxError thrown

for (var i = 0; i < 10; i++) {
    function bar () {  }
    bar();
}
// SyntaxError thrown

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment