JavaScriptSyntax & Statements

Syntax & Statements

Every language has rules for how its source code is allowed to look. JavaScript's syntax is forgiving on the surface — you can leave out semicolons, mix quote styles, and the engine will usually do something sensible. Underneath, there are a handful of rules worth knowing well, because the places JavaScript is most quietly weird are exactly the places you write code every day.

Statements vs expressions

A statement does something. An expression produces a value. Most programs are a stack of statements, and many statements contain expressions.

JS
// statement: declaration
let total = 0;

// statement: assignment, with an expression on the right
total = 1 + 2 * 3;

// statement: a function call used for its side effect
console.log(total);

// statement: control flow
if (total > 0) {
  total -= 1;
}

The right-hand side of = is an expression — 1 + 2 * 3 evaluates to a value (7). The whole line is a statement that assigns that value to a variable. The distinction matters because some places in the language only accept expressions (function arguments, the parts of a ternary, template literal interpolations) and some only accept statements (the body of an if, the top level of a file).

Semicolons and ASI

JavaScript statements end with a semicolon — but the engine inserts one for you in most cases, a process called Automatic Semicolon Insertion (ASI). So both of these run identically:

JS
const a = 1;
const b = 2;
console.log(a + b);

// also valid
const a = 1
const b = 2
console.log(a + b)

ASI sounds magical, but it is mechanical: the parser inserts a semicolon only at very specific spots (line breaks, before }, at end-of-file). The trap is that it does not insert one when the next line could continue the previous statement.

A classic ASI bug

JS
function value() {
  return
  {
    ok: true
  }
}

console.log(value());
undefined

ASI inserted a semicolon right after return, so the function returns undefined and the object literal is dead code. Put the { on the same line as return, or pick a style and stick with it.

The two ASI footguns
Lines starting with `(`, `[`, `/`, `+` or `-` can attach to the previous line. If you omit semicolons, prefix those lines with a leading semicolon, or just keep semicolons everywhere. Either rule, applied consistently, is fine.
Case sensitivity

JavaScript is case-sensitive. userName, username, UserName and USERNAME are four different identifiers.

JS
let total = 100;
console.log(Total); // ReferenceError: Total is not defined

Keywords are lowercase: if, for, return, const, function, class. Built-in constructors are capitalised: Array, Object, Date, Promise. The convention is camelCase for variables and functions, PascalCase for classes and constructors, and UPPER_SNAKE_CASE for true constants.

Identifiers — what you can name things

A valid identifier:

  • Starts with a letter, _ (underscore) or $ (dollar sign).

  • Subsequent characters can also include digits.

  • Can use most Unicode letters — const π = 3.14159 is valid.

  • Cannot be a reserved word (class, return, if, let, await, etc.).

JS
let userName = "Ada";     // ok
let _private = 42;        // ok
let $element = null;      // ok (common in jQuery-era code)
let 1stPlace = "gold";    // SyntaxError — starts with a digit
let class = "intro";      // SyntaxError — reserved word
Whitespace and line breaks

Spaces, tabs and most newlines are ignored by the parser — except when they trigger ASI (above) or sit inside a string. Indent for readability; the engine doesn't care. Two spaces, four spaces or tabs: pick one, configure your editor, and let Prettier or your formatter enforce it.

Strings are literal
Spaces, tabs and newlines *inside* a string are part of the string. `"hello world"` keeps every space. Template literals (backticks) also keep newlines.
Strict mode

Modern JavaScript has a stricter dialect you can opt into with a directive at the top of a file or function:

JS
"use strict";

x = 10;             // ReferenceError — assigning to an undeclared variable

function bad() {
  "use strict";
  let arguments = []; // SyntaxError in strict mode
}

Strict mode turns silent mistakes into errors, forbids a few legacy features and lets the engine optimise more aggressively. You almost never need to type the directive yourself because ES modules and class bodies are strict by default. If you are writing a classic <script> or a CommonJS file, opt in.

Blocks and the optional semicolon-after-}

A block is a pair of { ... } containing zero or more statements. Blocks don't take a semicolon after the closing brace, except when they are part of an expression statement — most often a function expression or object literal assigned to a variable.

JS
if (true) {
  console.log("hi");
}                       // no semicolon needed

const greet = function () {
  console.log("hi");
};                      // semicolon — this is an assignment statement

const user = {
  name: "Ada",
};                      // semicolon — object literal in an assignment
Pick a style and let tools enforce it
Don't argue about semicolons or quote style with humans — install Prettier (or your project's formatter) and let it run on save. Style discussions are noise; consistency is what actually helps readers.