Menu
Try in Playground

JavaScript Syntax and Semicolons: ASI Rules Explained

How JavaScript syntax works — statements, blocks, expressions — and the real story on semicolons, automatic semicolon insertion, and when it bites you.

JavaScript Code Is a Sequence of Statements

A JavaScript program is a list of statements — instructions the engine runs top to bottom. Declaring a variable is a statement. Calling a function is a statement. An if or a for block is a statement. Statements are separated from each other by semicolons.

index.js
Output
Click Run to see the output here.

Three statements, three semicolons. The engine runs the first, then the second, then the third. Simple enough.

Whitespace and indentation don't mean anything to the parser. You could put all three on one line with semicolons between them and it would run identically. We indent for human readers, not for the engine.

Blocks Group Statements Together

Curly braces { } create a block — a group of statements the engine treats as a unit. You'll see blocks everywhere: function bodies, if branches, loop bodies.

index.js
Output
Click Run to see the output here.

The two console.log calls inside the braces are the body of the if. Notice there's no semicolon after the closing } — blocks aren't statements that need terminating. The if statement as a whole ends when the block ends.

This catches people who come from languages where every } wants a ; after it. In JavaScript, a standalone block or control-flow block does not.

Expressions vs. Statements

One distinction worth getting clear early: expressions produce a value, statements do something.

  • 2 + 3 is an expression. It evaluates to 5.
  • let x = 2 + 3; is a statement. It declares a variable and assigns the result of an expression to it.
  • console.log("hi") is an expression (a function call returns undefined), but written on its own line with a semicolon it becomes an expression statement.
index.js
Output
Click Run to see the output here.

Most of the time you don't have to think about this. It matters when you meet arrow functions, ternaries, and places where JavaScript wants an expression but you tried to give it a statement (or the other way around).

The Semicolon Question

Here's the honest answer: JavaScript has a feature called Automatic Semicolon Insertion (ASI) that inserts missing semicolons for you at most line breaks. That means code like this runs fine:

index.js
Output
Click Run to see the output here.

No semicolons, no error. ASI looks at each line break and asks, "could the next token continue the current statement?" If not, it inserts a semicolon.

Because of ASI, two legitimate styles exist in the wild:

  • Semicolons always. Most codebases, most tutorials, most style guides.
  • No semicolons. Used by some modern projects (Standard style, some React codebases). Relies on ASI plus a couple of defensive tricks.

Both work. Neither is "wrong." What is wrong is inconsistency — mixing styles inside one file makes bugs harder to spot.

Where ASI Bites You

ASI does the right thing ~99% of the time. The remaining 1% is lines that start with a token that could continue the previous line. The troublemakers are [, (, `, +, -, and /.

Look at this:

index.js
Output
Click Run to see the output here.

You'd expect x and y to swap. Instead, ASI doesn't insert a semicolon before [x, y] because 10[x, y] is syntactically valid (indexing into the number 10). The parser reads line 2 and line 3 as one big expression, and you get a runtime error or garbage output.

The fix is either a semicolon at the end of line 2:

index.js
Output
Click Run to see the output here.

Or, if you're writing in no-semicolon style, a leading semicolon on the risky line:

index.js
Output
Click Run to see the output here.

That leading ; is the defensive trick no-semicolon codebases use. It looks odd until you know why it's there.

The return Trap

One ASI case is worth memorising because it produces silent bugs. If you put a line break right after return, ASI inserts a semicolon there, and the function returns undefined:

index.js
Output
Click Run to see the output here.

The author meant to return an object. ASI saw return at the end of a line and terminated the statement on the spot. The object literal became unreachable code.

The fix is to start the value on the same line as return:

index.js
Output
Click Run to see the output here.

The same rule applies to throw, break, continue, and yield — don't put a line break between the keyword and its value.

A Simple Rule That Works

If you're starting out, the easiest path is:

  1. Write semicolons explicitly at the end of every statement.
  2. Don't put them after block-closing } for if, for, while, function declarations, or class bodies.
  3. Do put them after } for an object literal or a function expression assigned to a variable: const f = function() {};.
  4. Use a formatter (Prettier, ESLint with a style rule) and stop thinking about it. The formatter enforces whatever your team decided.
index.js
Output
Click Run to see the output here.

This rule isn't universal law — it's the convention you'll see in the majority of JavaScript you read. Stick with it until you have a reason not to.

Case Sensitivity and Identifiers

Two small rules that live here too:

  • JavaScript is case-sensitive. userName, username, and UserName are three different identifiers.
  • Identifiers can contain letters, digits, _, and $, but can't start with a digit. They can't be reserved words like class, return, or function.
index.js
Output
Click Run to see the output here.

The $ is legal but usually reserved by convention for library-specific things (jQuery used it historically, some template systems still do). You rarely pick it yourself.

Next: Strict Mode

Modern JavaScript quietly runs in a tighter variant of the language called strict mode, which turns a handful of sloppy behaviors into real errors. ES modules and class bodies are strict by default, but it's worth knowing what that actually changes — that's the next page.

Frequently Asked Questions

Do you need semicolons in JavaScript?

Technically no — JavaScript has Automatic Semicolon Insertion (ASI), which adds them for you at most line breaks. In practice, most teams still write them explicitly because ASI has a handful of edge cases (lines starting with [, (, `, +, -, /) where it does the wrong thing. Pick a style and let a formatter like Prettier enforce it.

What is automatic semicolon insertion in JavaScript?

ASI is the rule that lets JavaScript insert missing semicolons at the end of a line when the next token couldn't continue the current statement. It's why let x = 1 works without a semicolon. It fails when a line happens to start with something that can continue the previous line — like [ or ( — and JavaScript quietly glues the two lines together.

What's the basic syntax of a JavaScript statement?

A statement is an instruction — a variable declaration, a function call, an if block, a loop. Statements are separated by semicolons (explicit or inserted). Blocks of statements go inside { }. Whitespace and indentation are ignored by the parser, so formatting is for humans, not the engine.

Learn to code with Coddy

GET STARTED