· 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.

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.
- 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.
- IIFE (Immediately Invoked Function Expression) and previous expression
let a = 1(function () {
console.log('IIFE');
})();
// This will throw: TypeError: 1 is not a functionWithout a semicolon before the IIFE, the parser treats the (function(){...})() as a call on 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: falseas 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?
- Douglas Crockford - historically favors defensive practices, including semicolon usage in many of his examples and writings: https://www.crockford.com/javascript/
- Feross Aboukhadijeh - creator of StandardJS, advocates for a semicolon-free style because it removes one axis of configuration: https://standardjs.com/
- Airbnb Engineering - their widely used guide requires semicolons: https://github.com/airbnb/javascript#semicolons
- Prettier team - focuses on consistent formatting; Prettier can enforce either style depending on configuration: https://prettier.io/
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.
- ESLint’s rule
semienforces presence or absence: https://eslint.org/docs/rules/semi- Example:
"semi": ["error", "always"]or"semi": ["error", "never"]
- Example:
- Prettier’s option
semicontrols output formatting:semi: trueorsemi: false(defaults totrue): https://prettier.io/docs/en/options.html#semicolons - StandardJS is a complete style + linter combo that opts out of semicolons: https://standardjs.com/
A typical team setup:
- Decide semicolons or not.
- Configure Prettier to format automatically.
- Use ESLint with the
--fixoption 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
- Safety-first codebase (high-consequence, many contributors, mixed tooling): choose semicolons (
semi: true). - New project, small team, developer ergonomics matters, and you like StandardJS/Prettier workflows: consider no-semicolons (
semi: false). - 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
- MDN - Automatic Semicolon Insertion: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#automatic_semicolon_insertion
- Airbnb JavaScript Style Guide: https://github.com/airbnb/javascript#semicolons
- StandardJS: https://standardjs.com/
- Prettier options: https://prettier.io/docs/en/options.html#semicolons
- ESLint
semirule: https://eslint.org/docs/rules/semi - Douglas Crockford - JavaScript resources and writings: https://www.crockford.com/javascript/
Make your pick. Then automate it. The semicolon war isn’t ended by consensus - it’s ended by habit and tooling.



