· tips  · 5 min read

To Semicolon or Not to Semicolon: The Great JavaScript Debate

Explore the semicolon debate in JavaScript: how Automatic Semicolon Insertion (ASI) works, real-world pitfalls, arguments for both sides, what influential developers and major style guides recommend, and a practical team decision flow to pick the right approach for your project.

Explore the semicolon debate in JavaScript: how Automatic Semicolon Insertion (ASI) works, real-world pitfalls, arguments for both sides, what influential developers and major style guides recommend, and a practical team decision flow to pick the right approach for your project.

What you’ll get from this article

You’ll leave knowing why JavaScript developers fight over a single punctuation mark, when semicolons actually matter, which influential people and style guides take which side, and how to decide - pragmatically - what your team should do next.

This isn’t about dogma. It’s about safety, readability, tooling and ship-ready standards.

A very short history and the technical core: Automatic Semicolon Insertion (ASI)

JavaScript’s grammar allows many semicolons to be optional. When the parser expects a semicolon but doesn’t find one, the language sometimes inserts one automatically. This behavior is called Automatic Semicolon Insertion (ASI).

Read MDN’s explanation for the authoritative details: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion

Why this matters: ASI works most of the time, but there are specific cases where removing semicolons changes program behavior - sometimes subtly, sometimes catastrophically.

Real examples: where ASI bites you

Here are the classic pitfalls you need to know. Try these in your head or REPL to see the differences.

  1. return on its own line
function getObject() {
  return;
  {
    ok: true;
  }
}

console.log(getObject()); // -> undefined (not {ok: true})

Because return is followed by a newline, ASI inserts a semicolon after return, so the function returns undefined.

  1. IIFE (Immediately Invoked Function Expression) and previous expression
let a = 1(function () {
  console.log('IIFE');
})();

// This will throw: TypeError: 1 is not a function

Without a semicolon before the IIFE, the parser treats the (function(){...})() as a call on 1.

  1. Leading [ or (
let x = 3;
let y = x[(1, 2, 3)].forEach(console.log);

// Without semicolon after `let y = x` this can be parsed as y[1,2,3]...

These are the kinds of edge cases that make people say: “Don’t mess with semicolons.”

For a fuller set of gotchas see MDN and other deep dives: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion

The case for semicolons - clarity and safety

Here are the strongest arguments in favor of always using semicolons:

  • Predictability: You know exactly where a statement ends. No mental context-switching to check if ASI will do the right thing.
  • Fewer footguns: Return/newline, IIFE, unary operators, and some minification transformations can break when semicolons are missing.
  • Common corporate and legacy code style: Many large codebases and style guides require semicolons. For example, the Airbnb JavaScript Style Guide requires them: https://github.com/airbnb/javascript#semicolons
  • Easier for some tools and code generators: Explicit terminators make certain programmatic transformations simpler.
  • Authority endorsements: Douglas Crockford - a long-time JavaScript commentator and author of JavaScript: The Good Parts - has historically emphasized defensive programming practices that include semicolons (see his resources): https://www.crockford.com/javascript/

If you’d rather avoid surprises and minimize debugging sessions caused by ASI, semicolons are a defensible choice.

The case against semicolons - minimalism and ergonomics

On the other side, many developers prefer to omit semicolons entirely. Why?

  • Less visual clutter: Cleaner lines, fewer keystrokes.
  • ASI handles the vast majority of cases correctly; in well-structured code the problems are rare.
  • Tooling can enforce and fix style: Formatters and linters (e.g., Prettier, ESLint) normalize the output so teams don’t argue about placement.
  • Cultural movement: Projects like StandardJS advocate no semicolons as a way to reduce configuration and friction. StandardJS (created by Feross Aboukhadijeh) deliberately set semi: false as a strong opinion: https://standardjs.com/
  • Community examples: Many modern projects embrace the terser syntax.

Prettier’s default configuration historically favored semicolons, but it provides a semi option that lets teams choose: https://prettier.io/docs/en/options.html#semicolons

Voices from the field: who champions what?

Different influential maintainers have different opinions. The point isn’t that one is right and the others wrong - it’s that their preferences have shaped widely used tools and conventions.

Tooling: ESLint + Prettier and how to enforce your choice

Pick a side - then automate it.

A typical team setup:

  1. Decide semicolons or not.
  2. Configure Prettier to format automatically.
  3. Use ESLint with the --fix option in CI and pre-commit hooks (Husky) to prevent style drift.

That removes subjective debate from pull requests and keeps merge friction low.

A practical decision flow for teams

  1. Safety-first codebase (high-consequence, many contributors, mixed tooling): choose semicolons (semi: true).
  2. New project, small team, developer ergonomics matters, and you like StandardJS/Prettier workflows: consider no-semicolons (semi: false).
  3. Existing codebase: follow the established convention unless you intentionally plan a migration with tooling and CI.

Make the rule explicit in your README or CONTRIBUTING.md and codify it in your linter/formatter config.

Examples of ESLint + Prettier snippets

Package.json scripts and configs are common places to show intent. Example ESLint rule (in .eslintrc.json):

{
  "rules": {
    "semi": ["error", "always"]
  }
}

Prettier option (in .prettierrc):

{
  "semi": false
}

Pick one and make it part of your CI so code can’t sneak in that violates the rule.

Final recommendation - consistency wins

Semicolons or no semicolons: neither choice is a bug by itself. What matters is consistency, automation, and awareness of the language’s corners.

  • If you prefer rock-solid predictability and fewer edge-case bugs, use semicolons.
  • If you prefer a lean syntax and are willing to rely on strong tooling (Prettier/ESLint) to avoid pitfalls, you can safely omit them.

Either way, document the decision, enforce it with tools, and educate your team about the few cases where ASI can surprise you.

Further reading and references

Make your pick. Then automate it. The semicolon war isn’t ended by consensus - it’s ended by habit and tooling.

Back to Blog

Related Posts

View All Posts »
The Magic of Default Parameters: Avoiding Undefined Errors

The Magic of Default Parameters: Avoiding Undefined Errors

Default parameters turn brittle functions into resilient ones. Learn how to use defaults in JavaScript, Python and TypeScript to avoid 'undefined' bugs, sidestep common pitfalls like mutable defaults and falsy-value traps, and make your code clearer and safer.