Loading...

JavaScript Strict Mode

Strict mode is a switch that refuses a few silent mistakes. Put "use strict" first. Then size = "regular", with no let and no const, throws ReferenceError instead of inventing a global. The line on this page is ReferenceError.

Not the to-do, and not the errors page

The to-do ended on done: buy tea. The errors page threw new Error("missing size") on purpose, and catch read that message. This page does not throw your own Error. The engine throws because the name size was never declared. console.error still does not throw.

The directive has to be first

"use strict" counts only when it is the first statement of the script, or the first statement inside one function. A string later in the file is an ordinary expression and changes nothing. A function can be strict while the rest of the script is not. Modules are already strict, so the directive there is redundant.

An undeclared name is a real failure

setSize assigns size without declaring it. The call sits in try. Strict mode does not create a global size.

Undeclared assignment

javascript
"use strict";
function setSize() {
size = "regular";
}
try {
setSize();
} catch (error) {
console.log(error.name);
}

The log is ReferenceError. Repair it by declaring the name: let size = "regular". With { drink: "tea" } and that declared size, a label can return tea / regular. Assigning order.size is the other honest repair, because that name does exist.

A bare call has no this

Calling a function by its name does not set this. In strict mode this is undefined. Calling a method on the order still sets this to that object, so this.drink is tea.

this in a bare call

javascript
"use strict";
function bare() {
return this;
}
const order = {
drink: "tea",
label() {
return this.drink;
}
};
console.log(bare());
console.log(order.label());

The logs are undefined, then tea. Do not read this.drink inside bare. There is no object there, so that read would throw.

Four changes worth remembering

The left column is the old silent behavior. The right column is what this directive does.

📊 What strict mode changes

Situation Without the directive With "use strict"
size = "regular" and no declaration creates a global ReferenceError
this in a bare call the global object undefined
Two parameters with the same name the last one wins SyntaxError
delete on a declared variable returns false SyntaxError

A duplicate parameter or delete size fails while the script is being read, so try cannot catch it. ReferenceError from the assignment happens when the function runs, so catch can see it. Deleting an object property, delete order.drink, is still allowed in both modes when that property can be removed.

The line

The page is one strict script. The assignment fails, and the name of that error is written on the page.

Page demo — ReferenceError

html
<!DOCTYPE html>
<html>
<body>
<p id="line">…</p>
<script>
"use strict";
const line = document.querySelector("#line");
try {
size = "regular";
} catch (error) {
line.textContent = error.name;
}
</script>
</body>
</html>

The line reads ReferenceError. It does not read done: buy tea, and it does not read caught / missing size. Add let in front of size and this catch stops running.

At the counter

  1. Run setSize under "use strict". The log is ReferenceError.
  2. Change the assignment to let size = "regular". The throw is gone.
  3. Call bare(). The value is undefined.
  4. Call order.label(). The value is tea.
  5. Read the page. The line is ReferenceError.

Misses

The directive is not a comment you can drop anywhere. A method call is not a bare call.

  • Putting "use strict" after another statement, where it does nothing
  • Expecting an undeclared assignment to create a global
  • Reading this.drink inside a bare call
  • Catching a duplicate parameter with try, which never runs because the script does not parse
  • Reading the line as done: buy tea
  • Reading the line as caught / missing size

Keep this

  • "use strict" must be the first statement of the script or of that function
  • An undeclared size = "regular" throws ReferenceError
  • A bare call's this is undefined; order.label() still returns tea
  • Duplicate parameters and delete on a variable are syntax failures
  • The page line is ReferenceError

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

❓
6
Questions
🎯
70%
To Pass
♾️
∞
Time
🔄
∞
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top