It’s a common place, when you get into a Js interview, one of the first questions they usually ask is: What is ‘use strict’ and what it does to the application?
I know this is kind of old now, but it still comes up in almost every interview, so let’s talk a little bit about it and really see what it does to the application.
First, let’s take a look at the definition.
JavaScript’s strict mode, introduced in ECMAScript 5, is a way to opt in to a restricted variant of JavaScript, thereby implicitly opting-out of “sloppy mode“. Strict mode isn’t just a subset: it intentionally has different semantics from normal code. Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don’t rely on strict mode without feature-testing for support for the relevant aspects of strict mode. Strict mode code and non-strict mode code can coexist, so scripts can opt into strict mode incrementally.
Strict mode makes several changes to normal JavaScript semantics:
- Eliminates some JavaScript silent errors by changing them to throw errors.
- Fixes mistakes that make it difficult for JavaScript engines to perform optimizations: strict mode code can sometimes be made to run faster than identical code that’s not strict mode.
- Prohibits some syntax likely to be defined in future versions of ECMAScript.
Now let’s talk about what happens to your code when you enable strict mode.
First, strict mode makes it impossible to accidentally create global variables. In normal JavaScript mistyping a variable in an assignment creates a new property on the global object and continues to “work”. Assignments, which would accidentally create global variables, instead throw an error in strict mode:
test = 'some string'; // create a global variable
console.log(test); // prints 'some string'
Now in Strict Mode
'use strict'
test = 'some string'; // throw an error
console.log(test);
As you can see, Strict Mode prevents the application from creating global variables and also prevents you from declaring variables without the keywords let and const.
Strict mode will also prevent global fallback when assigning this to functions. When you call a function without a context, the this of the function will be the global object in normal mode. In Strict mode, this will be undefined. Check out the cobe below:
let test = {
checkThis() {
console.log(this)
},
}
// calling checkThis with context
test.checkThis(); // prints out { checkThis: [Function: checkThis] }
// calling checkThis without context
let foo = test.checkThis;
foo() // prints out the Global object
Now the same code in Strict Mode:
'use strict';
let test = {
checkThis() {
console.log(this)
},
}
// calling checkThis with context
test.checkThis(); // prints out { checkThis: [Function: checkThis] }
// calling checkThis without context
let foo = test.checkThis;
foo() // prints out undefined
Another interesting use case showing the behavior above is the following:
(function () {
var a = b = 2
}())
console.log(a); // throws an error saying a in not defined.
console.log(b); // Prints out 2
What happens above is a classic case of a variable been defined in the global scope because it misses the keyword var, let or const. When you write:
(function () {
var a = b = 2
}())
Javascript is actually doing this:
(function () {
var a;
b = 2;
a = b;
}())
If you’re in a clojure like above, the a var will be local and not accessible outside of it, but when you declare b without the keyword var, even inside a clojure, the variable is created as a property of the global object and it is available globally.
Using ‘use strict’ at the top of that code would generate an error saying that you cannot declare a variable without a keyword.
Second, strict mode prohibits with. The code below will throw an error when you run with use strict:
'use strict';
let x = 10;
with (obj) { // error
console.log(x);
}
It also prevent eval from creating variables into the surrounding function or the global scope. In normal mode, variables created inside a eval call leak to the surrounding scope. Check the code below:
eval('var a = 10;');
console.log(a); // prints out 10
Adding ‘use strict’ solves this problem:
'use strict';
eval('var a = 10;');
console.log(a); // variable is undefined
Third, strict mode makes attempts to delete functions, variables or function arguments throw errors where before the attempt would simply have no effect:
var test = '';
delete test;
'use strict';
function foo() {};
delete foo;
Fourth, strict mode prior to Gecko 34 requires that all properties named in an object literal be unique. The normal code may duplicate property names, with the last one determining the property’s value. But since only the last one does anything, the duplication is simply a vector for bugs, if the code is modified to change the property value other than by changing the last instance. Duplicate property names are a syntax error in strict mode:
Fifth, strict mode requires that function parameter names be unique. In normal code the last duplicated argument hides previous identically-named arguments. Those previous arguments remain available through arguments[i]
, so they’re not completely inaccessible. Still, this hiding makes little sense and is probably undesirable (it might hide a typo, for example), so in strict mode duplicate argument names are a syntax error:
Sixth, a strict mode in ECMAScript 5 forbids octal syntax. The octal syntax isn’t part of ECMAScript 5, but it’s supported in all browsers by prefixing the octal number with a zero: 0644 === 420
and "\045" === "%"
. In ECMAScript 2015 Octal number is supported by prefixing a number with “0o
“. i.e.
Seventh, strict mode in ECMAScript 2015 forbids setting properties on primitive values. Without strict mode, setting properties is simply ignored (no-op), with strict mode, however, a TypeError
is thrown.