---
title: "12 — Strict Mode — Opting Into Stricter Rules"
uid: strict-mode
tags: ["use-strict", "roadmap:javascript", "strict-mode", "best-practices", "javascript"]
excerpt: "Strict mode is an opt-in variant that converts a class of silent failures into loud errors — and in modern JavaScript it's mostly the default already."
date: 2026-08-13T03:28:05+0000
source: https://www.aveshina.my.id/en/blog/strict-mode
---

That "use strict" line at the top of files looked like incantation until I learned what it switches. The idea that everything else hangs off: **strict mode is an opt-in variant of JavaScript that converts a class of silent, error-prone behaviors into loud errors — and in modern code it's almost always already on by default.** [1]

The framing that finally landed is the failure-mode view. JavaScript's original "sloppy mode" was forgiving in ways that produced bugs silently — assigning to an undeclared variable created a global, duplicate parameters were allowed, this defaulted to the global object. Strict mode's entire job is to make those mistakes throw, so I find them at the line that caused them instead of three features later.

## What changes in strict mode

The list of differences is long, but a handful cover almost everything I'd actually hit [1][2]:

- **Undeclared variables throw.** x = 5 without let/const/var creates a global in sloppy mode; in strict mode it's a ReferenceError. The single most valuable change.
- **this in plain functions is undefined, not the global object.** Stops the classic bug of accidentally mutating window from a constructor called without new.
- **Duplicate parameter names throw.** function f(a, a) {} was silently allowed; now it's a SyntaxError.
- **Deleting un-deletable properties throws.** delete Object.prototype silently no-ops in sloppy mode; strict mode rejects it.
- **Octal literals (010) and with statements are forbidden.** Both were footguns.
- **arguments and caller are cleaner.** arguments.callee and arguments.caller throw, and assigning to arguments doesn't leak out.

The common thread: every change turns a silent success into a loud failure for operations that were almost certainly mistakes.

## How to turn it on

Two scopes [1]:

```
// Whole script — must be the literal first statement
"use strict";
// everything below runs strict

// Single function
function strict() {
  "use strict";
  // strict here only
}
```

The string has to be the *literal first* statement; it's not parsed as code — it's a directive the engine recognizes. Putting it after any other statement makes it a no-op expression.

## Why I rarely write it anymore

The part that surprised me: **in modern JavaScript, strict mode is on by default in the places that matter** [1][2]:

- **ES modules** (<script type="module">, import/export, .mjs) are strict by default — no directive needed.
- **Classes** (class bodies) are strict by default.
- **Bundlers and transpilers** (most build setups) default to strict.

So the "use strict"; line is mostly a relic of pre-module scripts and legacy function-style files. I add it to standalone .js files that aren't modules (a quick utility, a bookmarklet) for safety; I omit it everywhere a module or class already enforces it.

## How I use this

The habit is: assume strict mode is on (because in modules and classes it is), write code that's strict-clean anyway (always declare variables, never rely on sloppy this), and add the directive only to non-module scripts as a belt-and-suspenders measure. The payoff isn't that strict mode unlocks new features — it doesn't. The payoff is that a category of bugs I used to chase (the mystery global, the mutated window) simply stops happening, because the line that would have caused it throws instead.

## References

[1] Mozilla, "Strict mode," MDN Web Docs, 2024. [Online]. Available: [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode)

[2] I. Kantor, "The modern mode, "use strict"," The Modern JavaScript Tutorial, 2024. [Online]. Available: [https://javascript.info/strict-mode](https://javascript.info/strict-mode)

```quiz
Q: In strict mode, what happens when you assign to a variable without declaring it (x = 5)?
- It creates a global variable x
- It throws a ReferenceError
correct: 1
explain: Sloppy mode silently creates a global. Strict mode throws ReferenceError, catching the typo (usually a missing let/const) at the line that caused it.

Q: Where is strict mode already on by default, requiring no directive?
- Classic <script> tags and plain function files
- ES modules (<script type="module">, import/export, .mjs) and class bodies
correct: 1
explain: Modules and classes are strict by default. The "use strict" directive is needed only for non-module scripts and legacy function-style files.

Q: In strict mode, what is `this` inside a plain function called as `f()` (no object, no new)?
- undefined
- the global object (window/global)
correct: 0
explain: Sloppy mode defaults this to the global object, which is how window got accidentally mutated. Strict mode makes it undefined, so accidental global mutation via this becomes impossible.

Q: Why is the "use strict" directive placed as the first statement?
- The engine recognizes it only as a literal leading directive; any code before it makes it a no-op expression
- It must run before other code for performance reasons
correct: 0
explain: "use strict" is a special directive the parser recognizes only when it's the literal first statement of a script or function. Place anything before it and it's just an unused string expression.

Q: Which operation does strict mode forbid that sloppy mode silently allowed?
- delete Object.prototype (deleting an undeletable property)
- declaring a variable with let
correct: 0
explain: Sloppy mode no-ops on delete of a non-configurable property. Strict mode throws. The pattern across all strict-mode rules: silent successes on likely-mistakes become loud errors.
```
