Strict mode
Learn how JavaScript strict mode turns silent mistakes into errors, how the "use strict" directive prologue works, and why modules and classes are strict automatically.
- 01Place the directive correctlyExplain why
"use strict"only counts in a directive prologue. - 02Predict strict-mode errorsCompare silent sloppy behavior with strict ReferenceError, TypeError, and SyntaxError results.
- 03Recognize modern defaultsKnow that ES modules and classes are strict without writing the directive yourself.
Strict mode in one sentence
Strict mode is JavaScript's modern checking mode. It keeps the language familiar, but it changes several older "I'll guess what you meant" behaviors into real errors you can see and fix.
You already know that JavaScript runs statements from top to bottom, and that small typos matter. Strict mode makes that lesson kinder: it catches more mistakes near the line where they happened instead of letting a confusing result appear later.
Sloppy mode is like a friend who nods along when you mispronounce a word. Strict mode is the tool that says, "Stop, that word is not in the dictionary." It feels stricter, but it saves you from carrying the typo into the rest of the program.
- In real life: A typo underlined immediately
- In JavaScript: An undeclared name throws
ReferenceError - In real life: A locked form refuses a bad entry
- In JavaScript: A read-only property throws
TypeError - In real life: A style guide that applies to this document
- In JavaScript: A directive prologue applies to this script or function
Where the analogy stops: A spelling checker suggests replacements. Strict mode usually just stops with an error; you still decide how to fix the code.
Strict mode is enabled for a classic script or function by putting the exact string "use strict" in its directive prologue. ES modules and class bodies are strict automatically.
This lesson compares old sloppy behavior with strict behavior, shows exactly where "use strict" has to go, and explains why the module code you will write in modern tools already gets these checks.
The "use strict" directive prologue
STEP THROUGH"use strict" looks like a string because it is one. At the start of a script or a function, JavaScript treats certain string expression statements as directives. The consecutive directives at the very top are called the directive prologue.
Whitespace and comments may come first. Other strings may come first too. But the moment JavaScript reaches a non-string statement, the prologue is over. A later "use strict" is just an unused string expression.
Choose where the directive appears, then step through the recorded result from a real JavaScript run.
script
try { typoTotal = 3; console.log("assignment worked");} catch (error) { console.log(error.name + ": " + error.message);}The first version catches typoTotal immediately. The second version prints setup first, ignores the late string, and creates globalThis.typoTotal. Same words, different position.
A directive can also start a function body. Only that function's code becomes strict. This helped older pages adopt strict mode one function at a time. Modern code usually chooses modules instead.
"use strict";as the first statement in a classic scriptconsole.log("hi");before"use strict";- A function body that starts with
"use strict"; - An ES module file
- A classic script with no directive
- Code inside a class body
Sort each fragment by whether it runs in strict mode. Remember: classic scripts need a directive prologue; modules and classes do not.
One more rule: you cannot turn strict mode off from inside strict code. A later string like "use sloppy" has no special meaning. This matters when build tools concatenate files: if a file's directive is no longer at the beginning of its new wrapper, it may stop working.
What strict mode changes
INTERACTIVEStrict mode is not a new language. Most normal JavaScript behaves the same. The important changes are the places where old JavaScript used to silently guess, ignore, or allow confusing code.
Sloppy mode lets some fouls slide and hopes the match still makes sense. Strict mode blows the whistle. That interruption is useful: you fix the foul while everyone still remembers where it happened.
- In real life: The whistle stops play now
- In JavaScript: An error stops the mistaken statement
- In real life: The replay shows exactly where the foul happened
- In JavaScript: The stack trace points near the bug
- In real life: Clean play continues as usual
- In JavaScript: Ordinary statements keep running the same way
Where the analogy stops: A referee can judge intent. JavaScript only follows rules: strict mode cannot tell whether a legal line is a good idea.
mistakeCount = 1;console.log("created global: " + ("mistakeCount" in globalThis));Classic scripts are sloppy unless a directive turns strict mode on.
Strict mode catches the typo instead of creating a new global name. Expected sloppy result: created global: true. Expected strict result: ReferenceError: mistakeCount is not defined.
| Behavior | Sloppy mode | Strict mode |
|---|---|---|
| Undeclared assignment | Creates a global property | Throws ReferenceError |
Plain function this | Becomes the global object | Stays undefined |
| Write to read-only data | Silently ignored | Throws TypeError |
| Duplicate parameter names | Allowed in old-style functions | SyntaxError before code runs |
Legacy octal like 010 | Means eight | SyntaxError; use 0o10 |
with statement | Changes how names are looked up | SyntaxError |
Do not memorize every historical corner today. Remember the pattern: strict mode refuses code that creates hidden globals, hides failed writes, or makes names hard to reason about.
Mistakes strict mode refuses before running
Some strict-mode changes are syntax rules. That means JavaScript rejects the program before any line runs. You see a SyntaxError, not a logged value.
"use strict";function total(a, a) { return a;} console.log(010); delete total; with ({ total: 1 }) { console.log(total);}- Duplicate parameter names are confusing because one name hides the other.
- Legacy octal numbers like
010look decimal to many readers. Use0o10for octal in modern code. - Deleting a plain variable never made sense as a cleanup tool. Variables are not object properties you can remove that way.
withchanges where names come from, so strict mode bans it. A later lesson, Sloppy mode in depth, revisits why old code had it.
If a strict script has a syntax error, try/catch inside that same script cannot catch it, because the script never starts running. Your editor, browser console, or test runner reports it before execution.
Strict by default in modules and classes
SORTES2015 made strict mode the default for two important modern features: modules and classes. If your file is an ES module, or if code is inside a class body, you do not need to write the directive.
// ES module file, or <script type="module">const moduleThis = this; class StrictCounter { count = 0; bump() { return this.count + 1; }} console.log(moduleThis === undefined);console.log(new StrictCounter().bump());In a module, top-level this is undefined, not the global object. Inside a class body, methods and field initializers use strict rules too. This is one reason modern tutorials and tools prefer modules: they start from the safer mode.
<script src="app.js"></script><script type="module" src="app.js"></script>class Counter { bump() { return this.count + 1; } }<script>total = 1;</script>
Decide whether each fragment needs "use strict"; to be strict, or whether JavaScript already makes it strict.
A plain <script> without type="module" is a classic script. Classic scripts are the place where the directive still matters most.
Where you will use this
You will not spend every day typing "use strict". You will spend every day benefiting from it. Frameworks, bundlers, and many editors produce or expect module code, so strict behavior is the normal modern starting point.
"use strict"; function saveProfile(profile) { profile.naem = "Ada"; // typo: meant profile.name return profile.name;} const profile = Object.freeze({ name: "Grace" });console.log(saveProfile(profile));The typo naem would be easy to miss if JavaScript quietly added a new property. Because the object is frozen and the code is strict, the bug becomes a TypeError near the write. That is much easier to debug than a missing name later in the app.
- Use modules when you can. They are strict automatically and fit modern tools.
- When writing an old-style classic script, put
"use strict";first. - When reading older code, recognize sloppy behavior instead of copying it into new files.
- When strict mode throws, treat the error as help: it found a bug early.
Common misconceptions
“Strict mode makes every program faster.”
It can remove confusing cases, but do not use it as a speed switch. Use it because it catches mistakes.
“A comment before "use strict" breaks it.”
Comments and whitespace are fine. A real non-string statement before it breaks the prologue.
“I can turn strict mode off later.”
No. Once code is strict, a later string cannot make that same code sloppy.
“Modules need "use strict" at the top.”
They do not. It is harmless, but redundant, because modules are strict by default.
“Strict mode fixes all bugs.”
It catches specific old-language hazards. Logic mistakes like adding the wrong number are still your job to test.
| Looks like | Where it appears | What it means |
|---|---|---|
"use strict"; | At the start of a script or function, before ordinary statements | A directive that enables strict mode |
"use strict"; | After console.log(...), let total = 0, or another ordinary statement | An expression statement whose value is ignored |
| A comment | Before the directive | Ignored by JavaScript; it does not end the prologue |
Practice: spot strict mode
5 EXERCISESRead the code and predict the exact error name printed by the catch block.
"use strict";
try {
usernmae = "Ada";
console.log("saved");
} catch (error) {
console.log(error.name);
}The program catches and prints ReferenceError. Strict mode refuses to create a global variable for the misspelled name usernmae.
Rewrite the program as a classic script that opts into strict mode. What statement must be first?
let total = 0;
total = total + 1;
console.log(total);"use strict";
let total = 0;
total = total + 1;
console.log(total);Put "use strict"; as the first statement. Then the rest of the classic script runs in strict mode and still prints 1.
This code creates a global instead of throwing. Type the short reason.
console.log("start");
"use strict";
missingName = 1;
console.log(globalThis.missingName);The directive is too late. console.log("start") is an ordinary statement before it, so the string on line 2 is ignored and the assignment stays sloppy.
What error name proves the frozen-object bug was caught?
"use strict";
const account = Object.freeze({ role: "reader" });
try {
account.role = "admin";
} catch (error) {
console.log(error.name);
}The catch block prints TypeError. The object is frozen, so account.role = "admin" cannot succeed; strict mode reports the failed write.
You are adding JavaScript to a small existing page. When would you choose <script type="module">, and when would a first-line directive in a classic script be enough?
For a new app, choose a module script because it is strict automatically and supports imports. For an older classic script you cannot convert yet, put "use strict"; first and test carefully.
Quiz: check your understanding
7 QUESTIONSPick the best answer. For code questions, the tests for this lesson run the same snippets so the answers match real JavaScript.
Question 1 of 7What does strict mode mainly do for a beginner?
Choose an answer to see the explanation.
Question 2 of 7Which placement turns a classic script strict?
Choose an answer to see the explanation.
Question 3 of 7What does this strict program print?
Read the code, then predict"use strict"; try { total = 1; } catch (error) { console.log(error.name); }Choose an answer to see the explanation.
Question 4 of 7What is
thisin a plain function call under strict mode?Read the code, then predict"use strict"; function showThis() { console.log(this === undefined); } showThis();Choose an answer to see the explanation.
Question 5 of 7Which code is strict without writing
"use strict"?Choose an answer to see the explanation.
Question 6 of 7Why can a late directive be dangerous when files are concatenated?
Choose an answer to see the explanation.
Question 7 of 7Which old feature does strict mode forbid because it makes names hard to predict?
Choose an answer to see the explanation.
Key takeaways
"use strict"only enables strict mode when it appears in the directive prologue of a script or function.- Strict mode turns several silent mistakes into visible errors, especially undeclared assignments and failed writes.
- It also rejects confusing syntax such as duplicate parameters, legacy octal literals, deleting variables, and
with. - Modules and class bodies are strict by default; classic scripts need the directive if you want strict mode.
- You cannot turn strict mode off from inside strict code.
Remember the one-liner.
Strict mode is JavaScript's safer modern mode: it stops old silent mistakes so you can fix them early.
Up next: Talking to the user.