Quick Reference for Changes in Strict Mode
The following is a quick reference containing a list of changes made in JavaScript's strict mode. For more information on how and when strict mode is enabled, refer to MDN's page on strict mode. That page also includes much (but not all) that's listed below in greater detail.
Reserved words
let implements
let interface
let let
let package
let private
let protected
let public
let static
let yield
// sloppy: Variables created
// strict: Error
Assign undeclared
doesNotExist = 0;
// sloppy: Creates global property
// strict: Error
Assign built-in globals
undefined = 0;
Infinity = 0;
NaN = 0;
// sloppy: Silently fails assignment
// strict: Error
Assign getter
const hasGetter = {
get getter() {},
};
hasGetter.getter = 0;
// sloppy: Silently fails assignment
// strict: Error
Assign non-writable
const hasReadOnly = {};
Object.defineProperty(hasReadOnly, "readOnly", { value: 1, writable: false });
hasReadOnly.readOnly = 0;
// sloppy: Silently fails assignment
// strict: Error
Assign to non-extensible
const nonExtensible = Object.preventExtensions({});
nonExtensible.any = 0;
// sloppy: Silently fails assignment
// strict: Error
Assign primitive properties
"string".prop = 0;
true.prop = 0;
(0.0).prop = 0;
// sloppy: Silently fails assignment
// strict: Error
Delete non-configurable
const hasNonConfig = {};
Object.defineProperty(hasNonConfig, "nonConfig", { value: 1, configurable: false });
delete hasNonConfig.nonConfig;
// sloppy: Does not delete, evaluates to false
// strict: Error
Delete unqualified identifier
delete identifier;
// sloppy: Deletes and evaluates to true if identifier is a deletable global,
// otherwise does not delete and evaluates to false
// strict: Error
Delete from proxy with trap returning falsy
const hasDeleteTrap = new Proxy(
{},
{
deleteProperty() {
return false;
},
}
);
delete hasDeleteTrap.any;
// sloppy: No error
// strict: Error
with
blocks
with ({}) {
}
// sloppy: No error
// strict: Error
Initializers in for-in
variable declarations
for (var x = 0 in {}) {}
// sloppy: No error, identifier will be assigned to initializer value if no iterations
// strict: Error
0-prefixed numeric literals
01;
08;
// sloppy: Evaluates to octal value if digit after 0 < 8, decimal if > 7
// strict: Error
Octal escapes in string literals
"\7";
// sloppy: Creates string '\x07'
// strict: Error
No in-scope declarations with eval
eval("var fromEval = 0");
// sloppy: Declaration in eval added to current scope
// strict: Declaration does not get added to current scope
eval
rebinding
eval = 0;
let eval;
function eval() {}
function fn(eval) {}
// sloppy: Rebinding succeeds
// strict: Error
Assign function expression name
const fn = function name() {
name = 0;
};
// sloppy: No error
// strict: Error
Labeled function declarations
label: function fn() {}
// sloppy: No error
// strict: Error
Block-scope function declarations
function outer() {
{
function inner() {}
}
inner();
}
// sloppy: Inner function scoped to outer function and can be called outside of block
// strict: Inner function scoped to block and cannot be called outside of block
Duplicate parameter names
function fn(a, a) {}
// sloppy: No error, last parameter of that name used in function body
// strict: Error
Function caller
, arguments
properties
function fn() {
fn.caller;
fn.arguments;
}
// sloppy: No error
// strict: Error
Arguments callee
property
function fn() {
arguments.callee;
}
// sloppy: No error
// strict: Error
Parameters mapped to arguments
function assignArg(param) {
arguments[0] = 1;
param = 2;
}
// sloppy: Assignment to arguments changes parameter value, assigning parameter changes arguments
// strict: Assignments do not change other values
arguments
rebinding
arguments = 0;
let arguments;
function arguments() {}
function fn(arguments) {}
// sloppy: Rebinding succeeds
// strict: Error
this
in function calls
function fn() {
return this;
}
// sloppy: Function sees `this` as global object
// strict: Function sees `this` as undefined
Nullish primitive this
in function calls
function fn() {
return this;
}
fn.call(null);
fn.call(undefined);
// sloppy: Function sees `this` as global object
// strict: Function sees `this` as original primitive
Non-nullish primitive this
in function calls
function fn() {
return this;
}
fn.call("string");
fn.call(true);
fn.call(0);
// sloppy: Function sees `this` as `Object(this)`
// strict: Function sees `this` as original primitive
Appendix
Changes in modules
ECMAScript modules are always in strict mode, but there are some additional changes that are specific to modules that do not apply to strict mode in other contexts.
Reserved words
let await;
// scripts: Variable created
// modules: Error
Duplicate function declarations
function fn() {}
function fn() {}
// scripts: Last declaration assigned to identifier
// modules: Error
Changes with parameters
Features used within parameter lists can also impact how JavaScript behaves with some strict mode-like behaviors observable in sloppy mode depending on how a parameter list is defined. These changes are seen when parameter lists contains any advanced features such as default parameters, rest parameters, or destructured parameters.
Duplicate parameter names
function simple(a, a) {}
function nonSimple(a, a = 0) {}
// simple parameter list: No error, last parameter of that name used in function body
// non-simple parameter list: Error
"use strict" directive
function simple(a) {
"use strict"
}
function nonSimple(a = 0) {
"use strict"
}
// simple parameter list: No error
// non-simple parameter list: Error
Parameters mapped to arguments
function simple(param) {
arguments[0] = 1;
param = 2;
}
function nonSimple(param = 0) {
arguments[0] = 1;
param = 2;
}
// simple parameter list: Assignment to arguments changes parameter value, assigning parameter changes arguments
// non-simple parameter list: Assignments do not change other values