Strict Mode in JavaScript

What is "Strict Mode"?

JavaScript has long been criticized for its quirks and unpredictability, especially in the early days. However, with the introduction of ECMAScript 5 (ES5) in 2009, developers were given the “use strict” directive, commonly known as “Strict Mode”. This mode allows for a safer and more predictable coding environment by catching common coding errors and preventing the use of potentially problematic features.

“Strict Mode” is a way to opt into a restricted variant of JavaScript that eliminates some silent errors by changing them to throw actual errors. It corrects errors that make it difficult for JavaScript engines to perform optimizations, and also prohibits some syntax that is likely to be defined in future versions of ECMAScript.

Enabling "Strict Mode"

Activating strict mode is simple. At the beginning of a script or a function, include the following line:

				
					"use strict";

				
			

Variable Declaration in "Strict Mode" in JavaScript

In “strict mode”, variable declarations have more stringent rules:

1. No Implicit Globals: In non-strict mode, assigning a value to an undeclared variable implicitly creates it as a global variable. However, in strict mode, this will throw an error.

				
					// Non-strict mode
undeclaredVar = "This is bad";  // Implicitly creates a global variable

// Strict mode
"use strict";
undeclaredVar = "This throws an error";  // ReferenceError: undeclaredVar is not defined

				
			

2. No Assignment to Read-only Properties: In strict mode, attempting to assign a value to a read-only property or a non-writable global variable will throw an error. For example, variables like undefined, NaN, and Infinity are read-only.

				
					"use strict";
undefined = "some value";  // TypeError: Cannot assign to read-only property 'undefined'

				
			

Function Declaration in "Strict Mode" in JavaScript

1. Preventing Duplicate Parameters: In “strict mode”, a function cannot have two parameters with the same name.

				
					"use strict";
function duplicateParams(a, a) {   // SyntaxError: Duplicate parameter name not allowed in this context
    // ...
}

				
			

2. Blocked Scope Functions in Strict Mode:

In ECMAScript 6 (ES6) and later, the behavior of block-scoped function declarations was standardized, especially when combined with “strict mode”. Previously, function declarations were always function-scoped or globally-scoped, depending on their location. With ES6, when using “strict mode”, functions declared inside a block are block-scoped, similar to let and const.

Here’s an example illustrating this:

				
					"use strict";

if (true) {
    function blockScopedFunction() {
        console.log("I'm block-scoped!");
    }
    blockScopedFunction();  // This works and logs "I'm block-scoped!"
}

try {
    blockScopedFunction();  // This throws an error since the function is block-scoped
} catch (error) {
    console.error(error.message);  // Logs: blockScopedFunction is not defined
}

				
			

In the above code:

  1. We’re using “use strict” to ensure that we are in strict mode.
  2. Inside the if block, we declare a function blockScopedFunction.
  3. Within the same block, we can call this function, and it works as expected.
  4. However, outside of this block, the function is not accessible, which is why it throws an error when we try to invoke it.

This behavior is a contrast to non-strict mode, where function declarations are hoisted and function-scoped.

Note: While block-scoped function declarations are part of the ES6 specification, their behavior may vary in different environments, and they can be considered less predictable than let or const. For this reason, it’s often recommended to use function expressions with let or const in block scopes for more consistent behavior:

				
					"use strict";

if (true) {
    const blockScopedFunctionExpression = function() {
        console.log("I'm also block-scoped, but using a function expression!");
    };
    blockScopedFunctionExpression();  // This works
}

// blockScopedFunctionExpression would be inaccessible here

				
			

'this' Reference in "Strict Mode" in JavaScript

JavaScript’s this keyword is notorious for its somewhat unpredictable nature, especially for developers coming from other programming languages. Depending on where and how it’s used, the value of this can vary. The introduction of “strict mode” in ECMAScript 5 (ES5) brings some much-needed clarity to the behavior of this, ensuring that it’s more consistent and less error-prone.

What is “this”?

In JavaScript, this is a special keyword that refers to the context in which a function is called. Its value is determined by how a function is invoked, not by where the function is defined. In different scenarios, this can refer to a global object, an instance of an object, the object currently being iterated over, or even undefined.

Behavior of ‘this’ in Non-strict Mode

In non-strict mode, the behavior of this can be perplexing:

Global Context (sloppy): When a function is called in the global context (i.e., not as a method of an object), this refers to the global object (window in browsers).

				
					function exampleFunction() {
    console.log(this); // Logs: Window {...}
}
exampleFunction();

				
			

Global Context (strict): In strict mode, this is undefined when a function is called in the global context.

				
					"use strict";
function exampleFunction() {
    console.log(this); // Logs: undefined
}
exampleFunction();

				
			

Object Method (sloppy): When a function is called as a method of an object, this refers to that object.

				
					const obj = {
    method: function() {
        console.log(this);
    }
};
obj.method(); // Logs: obj {...}

				
			

Object Method (strict): The behavior remains consistent with non-strict mode. When a function is called as a method of an object, this refers to that object.