Skip to main content

Strict mode in JavaScript

Strict mode is a JavaScript mode, activated by "use strict";, that makes the engine throw errors for patterns it would otherwise accept silently.

Theory

TL;DR

  • Think of it as a compiler warning system: sloppy JavaScript runs anyway, strict mode stops you before it gets bad.
  • Main difference: without strict mode, assigning to an undeclared variable creates a global; with it, you get a ReferenceError immediately.
  • this inside a regular function call returns undefined in strict mode, not window or global.
  • ES6 modules are strict by default. No directive needed.
  • Add it to every new file. The only exception: scripts targeting IE9 or older.

Quick example

javascript
// Without strict mode - creates a silent global variable function calcTotal(price) { subtotal = price * 1.1; // No error, but pollutes global scope return subtotal; } // With strict mode - fails at the source "use strict"; function calcTotal(price) { subtotal = price * 1.1; // ReferenceError: subtotal is not defined return subtotal; }

The first version runs fine and silently poisons the global object. The second stops you right where the problem is, not three functions later when something breaks in an unrelated place.

What strict mode actually changes

When the JS engine sees "use strict";, it switches to stricter parsing for that scope and all child scopes. During compilation, before any code runs, it flags octal literals (008), duplicate parameter names, and the with statement as SyntaxError. At runtime, undeclared variable assignments throw ReferenceError, and delete on a variable identifier throws SyntaxError.

The change that trips people up most: this inside a plain function call is undefined in strict mode. In sloppy mode it defaults to the global object. That default is responsible for a whole class of bugs where you write to window thinking you are writing to an object property.

When to use

  • New file or project: "use strict"; at the top. No downside.
  • Legacy codebase: add it per-file or per-function. Migrate gradually.
  • ES6 modules (.mjs, or type="module" in HTML): already strict. Skip the directive.
  • Third-party scripts you cannot control: wrap your own code in a strict IIFE instead of setting global strict.
  • The real exception: scripts that must run in IE9 or older.

How the engine handles it

V8 in Chrome and Node.js applies more aggressive JIT optimizations to strict code. The reason: no with statement to complicate scope resolution, no implicit globals, predictable this. In Node.js, pass --use-strict to enable it globally. Babel and webpack add "use strict" automatically when transpiling with @babel/preset-env.

Common mistakes

Assuming function-level strict affects the caller:

javascript
function parent() { x = 1; // No error - parent is in sloppy mode } function child() { "use strict"; y = 2; // ReferenceError - child is strict }

Strict mode applies only to its own scope. The parent stays sloppy. This creates confusion in codebases where only some files have the directive.

Trying to delete a variable:

javascript
"use strict"; var total = 100; delete total; // SyntaxError: Delete of an unqualified identifier in strict mode

In sloppy mode, delete on a variable silently returns false. In strict mode it is a SyntaxError.

Expecting eval() to inherit strict mode:

javascript
"use strict"; eval("x = 1"); // Still pollutes global scope - eval needs its own directive // Fix: eval('"use strict"; x = 1;');

Common Node.js gotcha that appears regularly in interview scenarios.

Duplicate parameter names:

javascript
"use strict"; function add(a, a) { // SyntaxError before any code runs return a + a; }

Sloppy mode accepts this without a word. Strict mode catches it at parse time.

Real-world usage

  • React: Babel adds "use strict" to every transpiled file via @babel/preset-env.
  • Node.js: core modules like fs use strict internally. Your app.js should too.
  • Express: production starters set strict at file level to prevent global leaks in route handlers.
  • Lodash: strict mode since v4.0, which removed a category of prototype-related issues.
  • jQuery: v3+ runs in strict mode.

I have seen global variable leaks from Express route handlers cause memory issues in Node.js production environments. Strict mode would have caught those assignments at startup, not three weeks later in a postmortem.

Follow-up questions

Q: What does "use strict" do to this in a regular function call?


A: Sets it to undefined instead of the global object. So this.name = "x" inside that function throws TypeError, instead of silently adding name to window.

Q: How do you enable strict mode in ES6 modules?


A: You do not. All ES6 modules are strict by default. Class bodies are strict too.

Q: Name three things strict mode bans.


A: Octal literals (08), duplicate parameter names, and the with statement. Also variable deletion and undeclared variable assignments.

Q: Can you mix strict and sloppy code in the same project?


A: Yes. Strict mode is per-scope. A sloppy function that calls a strict function stays sloppy on its own side. The mistake is assuming strict propagates upward to callers.

Q: Does strict mode affect performance?


A: Slightly positive. V8 applies more aggressive JIT optimizations in strict code because there are fewer edge cases in scope resolution. Small effect, but real.

Examples

Basic: undeclared variable enforcement

javascript
"use strict"; function processOrder(amount) { // Without a declaration this would silently become a global total = amount * 1.2; // ReferenceError: total is not defined return total; } processOrder(100);

The error points exactly to the missing const or let. Without strict mode, total lands on window and you spend time tracking it across multiple files.

Intermediate: this in a detached function call

javascript
"use strict"; const obj = { name: "strictObj", method() { // Arrow function: this is lexically bound to obj return () => this.name; }, looseMethod() { // Regular function: this depends on how it is called return function() { return this.name; }; } }; console.log(obj.method()()); // "strictObj" - arrow preserves this console.log(obj.looseMethod()()); // undefined in strict mode (window.name in sloppy)

looseMethod returns a plain function called without a receiver. Sloppy mode gives it window. Strict mode makes it undefined, which exposes the bug instead of hiding it behind the global object.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?