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.
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"
- 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
andarguments
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
andarguments.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 ofthis
is no longer the case. Instead,this
would beundefined
.
"use strict";
function foo() { return this; }
foo() === undefined
foo.call(1) === 1
foo.call("foo") === "foo"
foo.call(Number) === Number
arguments
andcaller
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