JavaScript Statements
A statement is a single instruction for the JavaScript engine to execute. Every program you write — from a one-liner to a million-line app — is just a sequence of statements running top to bottom. Get the rules right and your code is predictable; get them wrong and the engine silently inserts semicolons where you didn’t want them.
What Counts as a Statement?
let name = "Ada"; // declaration statement
name = name.toUpperCase(); // assignment statement
console.log(name); // expression statement
if (name) { /* ... */ } // control-flow statement
return name; // jump statement
Almost everything you write is a statement. The engine executes them one at a time, in order.
| Category | Examples |
|---|---|
| Declarations | let, const, function, class |
| Assignments / expressions | x = 5, myFn(), a + b (when used alone) |
| Control flow | if, else, switch, for, while |
| Jumps | return, break, continue, throw |
| Blocks | { ... } grouping zero or more statements |
Statements vs Expressions
This distinction trips up most beginners. An expression produces a value. A statement performs an action. Some statements contain expressions; some expressions are statements on their own.
2 + 3 // expression → 5
"hello" // expression → "hello"
isLoggedIn // expression → boolean
isLoggedIn = true // expression (assignment returns the value) AND a statement
let x = 5; // statement — declarations are not expressions
if (x) {} // statement — control flow is not an expression
| Expression | Statement | |
|---|---|---|
| Produces a value | ✅ | ❌ (most don’t) |
Can be used inside () |
✅ | ❌ |
Can stand alone with ; |
✅ (becomes expression statement) | ✅ |
| Examples | 1 + 1, fn(), a && b |
if, for, return, let x = 1 |
// Expression — can go anywhere a value is needed
const total = (2 + 3) * 4; // (2 + 3) is an expression
console.log(isLoggedIn ? "in" : "out"); // ternary is an expression
// Statement — cannot go inside ()
// const x = (if (true) 1 else 2); // ❌ SyntaxError
Semicolons — Are They Required?
Officially: every statement ends with a semicolon ;.
In practice: JavaScript has a feature called Automatic Semicolon Insertion (ASI) that adds them for you in most cases.
// Both are valid
let a = 1;
let b = 2;
let a = 1
let b = 2
But ASI has surprising edge cases:
// ❌ ASI inserts a semicolon after `return` — function returns undefined!
function getUser() {
return
{
name: "Ada"
}
}
console.log(getUser()); // undefined
// ✅ Keep the opening brace on the same line
function getUser() {
return {
name: "Ada"
};
}
// ❌ Two adjacent lines starting with [ or ( can merge into one statement
const a = 1
[1, 2, 3].forEach(console.log) // parsed as: 1[1,2,3].forEach(...) → TypeError
// ✅ Either add semicolons, or prefix the trap-line with one
const a = 1;
[1, 2, 3].forEach(console.log);
Tip: Pick a style and stick with it. The two dominant conventions are: “always semicolons” (Prettier default) and “no semicolons, ASI” (StandardJS). Both work — what matters is consistency, enforced by a linter or formatter.
Code Blocks — { ... }
A pair of curly braces groups statements into a block. Blocks are how you tell if, for, while, and friends what to run.
if (loggedIn) {
console.log("Welcome back");
showDashboard();
trackEvent("login");
}
A block can also stand alone, creating a new scope (covered in chapter 30):
{
const secret = 42;
console.log(secret); // 42
}
console.log(secret); // ❌ ReferenceError
Whitespace and Line Breaks
JavaScript ignores almost all whitespace. Spaces, tabs, and newlines are interchangeable for formatting — except where ASI cares.
// All equivalent
let x=1+2;
let x = 1 + 2;
let x = 1 + 2 ;
let result = 1
+ 2
+ 3
+ 4;
That said, your team and tools care about whitespace deeply. Use a formatter (Prettier) and never argue about it again.
One Statement Per Line — A Convention
You can put many statements on one line by separating them with semicolons. You shouldn’t:
// ❌ Hard to read, hard to debug
let a = 1; let b = 2; if (a < b) { console.log("smaller"); }
// ✅ One statement per line
let a = 1;
let b = 2;
if (a < b) {
console.log("smaller");
}
| Style | Readability | Debuggability |
|---|---|---|
| One statement per line | ✅ Clear | ✅ Stack traces map cleanly |
| Multiple per line | ❌ Cramped | ❌ Hard to set breakpoints |
Empty Statements
A single ; is a legal empty statement — it does nothing. Useful in loops where the work is done in the header:
// Read characters until EOF — body is just an empty statement
let ch;
while ((ch = readChar()) !== null); // semicolon = empty body
// But this is a common bug source:
if (loggedIn); // ❌ stray semicolon — the if has NO body
showDashboard(); // runs unconditionally!
Warning: Beware accidental ; right after if, for, or while. The statement is “complete” with no body, and the next line runs always.
Statement Execution Order
Statements run top to bottom, one at a time, on the single main thread.
┌─────────────────────────────┐
│ let x = 5; (1) │
│ console.log(x); (2) │ ┐
│ if (x > 0) { │ │
│ console.log("pos"); (3) │ │ executed in order
│ } │ │ 1 → 2 → 3 → 4
│ x = 0; (4) │ ┘
└─────────────────────────────┘
Asynchronous code (chapters 38–41) breaks this only at well-defined points (await, callbacks, promises). Synchronous statements always run in order.
Worked Example
// 1. Declarations
const PI = 3.14159;
let radius = 5;
// 2. Expression statement (call has a side effect)
console.log("Calculating...");
// 3. Assignment
const area = PI * radius ** 2;
// 4. Control flow + block
if (area > 50) {
console.log(`Large circle: ${area.toFixed(2)}`);
} else {
console.log(`Small circle: ${area.toFixed(2)}`);
}
// 5. Jump (in a function context)
function describe(r) {
if (r < 0) return "invalid";
return `radius ${r}`;
}
console.log(describe(radius));
// Output:
// Calculating...
// Large circle: 78.54
// radius 5
Every line is a statement. The engine reads them top to bottom and executes each one in sequence.
Best Practices Checklist
- ✅ One statement per line
- ✅ Use a formatter (Prettier) — let it handle semicolons
- ✅ Always use
{}blocks withif,for,while— even for one statement - ✅ Keep
returnand its value on the same line - ❌ Don’t rely on ASI in edge cases — write defensively
- ❌ Don’t put a
;immediately afterif,for, orwhile
What’s Next?
Statements give you the what — syntax rules tell you the how. Next we’ll cover the building blocks of valid code: keywords, identifiers, literals, operators, and the conventions that make code readable.