JavaScript Syntax

JavaScript syntax is the set of rules that defines how a valid JavaScript program must be written — how you combine keywords, values, operators, and punctuation so the JavaScript engine can parse and run your code. Just like English has grammar rules that determine whether a sentence makes sense, JavaScript has syntax rules that determine whether your code is valid. Understanding these rules deeply, rather than just imitating examples, is what lets you read any JavaScript code confidently and avoid the subtle bugs that trip up beginners.

Overview: How JavaScript Syntax Works

Before your code ever runs, the JavaScript engine (such as V8 in Chrome and Node.js) performs a step called parsing. During parsing, the engine reads your source code character by character and breaks it into small pieces called tokens — keywords like const, identifiers like total, operators like +, punctuation like { and ;, and literal values like 42 or "hello". The engine then arranges these tokens into a tree-like structure called an Abstract Syntax Tree (AST), which represents the grammatical structure of your program. Only after this tree is successfully built can the engine begin executing your code statement by statement.

If the tokens don’t fit together according to JavaScript’s grammar rules — for example, an unmatched bracket, a missing operator, or a keyword used where a value is expected — the parser throws a SyntaxError before a single line of your program executes. This is different from a runtime error (like calling a function that doesn’t exist), which only happens once execution reaches that specific line. A syntax error anywhere in a script file prevents the entire file from running.

A JavaScript program is made up of a sequence of statements. A statement is an instruction that performs an action: declaring a variable, running a loop, calling a function, or returning a value. Statements are usually terminated with a semicolon (;), though JavaScript can often infer where a statement ends on its own, through a mechanism called Automatic Semicolon Insertion (ASI), covered below. Statements are built from smaller building blocks called expressions — any piece of code that evaluates to a value, such as 2 + 2, userName.toUpperCase(), or simply 42.

JavaScript is also case-sensitive: myVariable, MyVariable, and MYVARIABLE are three completely different identifiers to the engine. This applies to keywords too — if is a keyword, but If or IF are just ordinary identifiers with no special meaning.

Syntax: The Building Blocks

The general shape of a JavaScript statement looks like this:

keyword identifier = expression;

For example: const total = price * quantity;. Here is a breakdown of the core syntax elements every JavaScript program is made of:

Element Description Example
Values / Literals Fixed data written directly in the code 42, "hello", true, null
Identifiers Names given to variables, functions, etc. userName, calculateTotal
Keywords Reserved words with special meaning let, const, function, if, return
Operators Symbols that act on values to produce a result +, =, ===, &&
Comments Text ignored by the engine, for humans only // note, /* note */
Whitespace Spaces, tabs, and newlines that separate tokens  
Punctuation Structural characters that group code { }, ( ), [ ], ;, ,

Identifier rules

  • Must start with a letter, $, or _ (never a digit).
  • After the first character, digits are allowed (e.g. value1).
  • Cannot be a reserved keyword (e.g. you cannot name a variable class or return).
  • Case-sensitive, and by convention written in camelCase.

Comments

Comments are ignored entirely by the parser and exist purely to document code for humans.

  • // single-line comment — everything from // to the end of the line is ignored.
  • /* multi-line comment */ — everything between the markers is ignored, even across several lines.

Examples

Example 1: Statements, values, and expressions

let firstName = "Ada";
let lastName = "Lovelace";
const fullName = firstName + " " + lastName;

console.log(fullName);
console.log(typeof fullName);
console.log(fullName.length);

Output:

Ada Lovelace
string
12

Each line here is a statement. firstName + " " + lastName is an expression — it evaluates to a single string value, which is then stored in fullName using the assignment operator =. Notice the two variables use different cases in spirit but identical spelling conventions; if you accidentally typed FirstName anywhere, JavaScript would treat it as an entirely separate, undeclared identifier and throw a ReferenceError at runtime.

Example 2: Case sensitivity and template literals

let age = 36;
let Age = 40; // a completely different variable from "age"

const summary = `Ada is ${age}, but the variable Age holds ${Age}`;
console.log(summary);

let x = 5
let y = 10
console.log(x + y)

Output:

Ada is 36, but the variable Age holds 40
15

This example proves two things: first, that age and Age are distinct identifiers because JavaScript is case-sensitive; second, that the statements let x = 5 and let y = 10 work perfectly fine without semicolons at the end. That’s Automatic Semicolon Insertion at work — the parser detects the newline and safely infers where each statement ends.

Example 3: Whitespace, blocks, and multi-line expressions

function calculateArea(width, height) {
  // A block statement groups code inside { }
  const area = width * height;
  return area;
}

const w = 4,
      h = 5;

console.log(
  calculateArea(w, h)
);

Output:

20

JavaScript almost entirely ignores extra whitespace and line breaks between tokens — the call to calculateArea is split across three lines purely for readability, and the engine parses it identically to a single-line version. The curly braces { } form a block statement, grouping multiple statements into one unit, which is how function bodies, if blocks, and loops are structured.

Under the Hood: What the Engine Actually Does

When you run a JavaScript file, the engine performs roughly these steps before your code produces any output:

  1. Tokenizing (lexing): the raw text is split into a stream of tokens — keywords, identifiers, literals, operators, and punctuation — while whitespace and comments are discarded (they exist only for humans).
  2. Parsing: the token stream is checked against JavaScript’s grammar rules and assembled into an Abstract Syntax Tree. If the tokens can’t legally combine (e.g. two operators in a row with no operand between them), parsing fails immediately with a SyntaxError, and nothing in the file executes.
  3. Automatic Semicolon Insertion: while building statements, the parser inserts a virtual semicolon wherever a line break occurs and the next token can’t validly continue the current statement. This is a convenience, not a substitute for understanding statement boundaries — it can insert a semicolon in a place you didn’t intend, which is a common source of bugs (see below).
  4. Compilation and execution: the engine compiles the AST to bytecode (and eventually optimized machine code for hot code paths) and begins executing statements from top to bottom, evaluating expressions and updating memory as it goes.

Understanding that parsing happens as a distinct, complete phase before execution explains why a syntax error on line 200 of a script prevents code on line 1 from running at all — the engine never got a valid tree to execute in the first place.

Common Mistakes

Mistake 1: Relying on ASI with a bare return

Automatic Semicolon Insertion silently breaks code when a newline appears right after return:

function getPerson() {
  return
  {
    name: "Ada"
  };
}

console.log(getPerson());

Output:

undefined

This looks like it should return an object, but ASI inserts an invisible semicolon immediately after return, turning it into return;. The object literal on the following lines is never reached. The fix is to keep the opening brace on the same line as return:

function getPerson() {
  return {
    name: "Ada"
  };
}

console.log(getPerson());

Output:

{ name: 'Ada' }

Mistake 2: Unterminated strings and mismatched punctuation

Forgetting a closing quote or bracket is one of the most common ways to trigger a SyntaxError. For example, writing const message = "Hello, World!; (missing the closing double quote) leaves the string unterminated, and the parser cannot figure out where the string value ends, so it throws a SyntaxError: Unterminated string literal before any code runs. The fix is simply to close every quote and bracket you open:

const message = "Hello, World!";
console.log(message);

Output:

Hello, World!

Modern code editors highlight matching brackets and quotes specifically to help catch this class of mistake before you even run the file.

Best Practices

  • Use semicolons explicitly at the end of statements rather than relying entirely on ASI — it makes intent unambiguous and avoids edge cases like the bare-return trap.
  • Always place opening braces { on the same line as the statement they belong to (if (x) {, not if (x)\n{) to sidestep ASI surprises.
  • Use a linter (such as ESLint) and let your editor’s syntax highlighting catch unmatched brackets and quotes as you type.
  • Follow consistent naming conventions — camelCase for variables and functions, PascalCase for classes — so case sensitivity works in your favor instead of causing confusion.
  • Prefer const and let over var; both enforce stricter, more predictable scoping rules that are part of writing correct modern syntax.
  • Use template literals (`${value}`) instead of string concatenation with + for readability once expressions get involved.
  • Keep one statement per line; don’t chain unrelated statements with semicolons on a single line just to save space.

Practice Exercises

  • Exercise 1: Declare two variables, city and City, with different string values. Log both to the console using a template literal in a single sentence, and confirm they don’t overwrite each other.
  • Exercise 2: Write a function called makeGreeting that returns an object literal { message: "Hello!" } using a return statement. Make sure the opening brace is on the same line as return so it doesn’t fall into the ASI trap described above.
  • Exercise 3: Take a block of code with inconsistent indentation and extra blank lines, and reformat it so it’s easier to read — then explain in your own words why the whitespace changes have zero effect on how the code executes.

Summary

  • JavaScript syntax is the grammar the engine uses to parse your code into an Abstract Syntax Tree before running it; a single syntax error blocks the entire file from executing.
  • Programs are built from statements, which are built from expressions, values, operators, and keywords.
  • JavaScript is case-sensitive: total and Total are different identifiers.
  • Whitespace between tokens is ignored by the parser and exists purely for human readability.
  • Automatic Semicolon Insertion lets you often omit semicolons, but it can silently change behavior — most notably with a bare return on its own line.
  • Comments (// and /* */) are stripped out during parsing and have no effect on execution.
  • Writing explicit semicolons, same-line braces, and consistent naming avoids the most common syntax-related bugs.