In the previous lesson you wrote your first program: a handful of lines that printed the summary of a Taller Nómada task. It worked, but you copied the shape without knowing the rules. Now you are going to learn them. Syntax is the grammar of the language: which symbols exist, how instructions are separated, what names you can use and how a program is read. Mastering it is what turns errors from "I have no idea what is going on" into "ah, there is a semicolon missing on line 12". It is the foundation absolutely everything else rests on.

Contents

  1. Statements and semicolons
  2. Automatic Semicolon Insertion (ASI)
  3. Blocks with braces {}
  4. Case sensitivity
  5. Rules and conventions for names
  6. Reserved words
  7. Whitespace, indentation and style
  8. Expressions versus statements
  9. Literals
  10. strict mode
  11. How a program is read from top to bottom
  12. Common Mistakes and Tips
  13. Exercises
  14. Conclusion

  1. Statements and semicolons

A program is a sequence of statements (or instructions): complete orders that the engine executes one after another. Each statement ends with a semicolon (;).

const title = 'Redesign the multipurpose room';
const assignee = 'Iván';
console.log(title, assignee);

There are three statements there: two declarations and one function call. They run in order, from top to bottom.

Technically you can put several on the same line if you separate them with ;, but do not do it: it reads far worse.

// Valid but unreadable: avoid it
const priority = 'high'; const hours = 12; console.log(priority, hours);

1.1 Statements that do not take a semicolon

There are important exceptions. Code blocks do not take a semicolon after the closing brace:

// Correct: there is no semicolon after the closing brace
if (priority === 'high') {
  console.log('Urgent task');
}

// A function declaration does not take one either
function showTask() {
  console.log('Taller Nómada task');
}

However, when a function is assigned to a variable, it does take a semicolon, because the complete statement is the assignment:

const showTask = function () {
  console.log('Taller Nómada task');
}; // ← this semicolon closes the assignment

The mental rule is simple: the semicolon closes a statement, not a block.

  1. Automatic Semicolon Insertion (ASI)

Here comes one of the most debated quirks of JavaScript. The language has a mechanism called ASI (Automatic Semicolon Insertion): if a line ends and the engine decides the statement is complete, it inserts a semicolon on its own.

That is why this code runs without errors:

const assignee = 'Lucía'
const hours = 8
console.log(assignee, hours)

So do you actually need to write them? The problem is that ASI gets it right almost always, but not always, and when it fails the resulting error is baffling.

2.1 The dangerous case: return

// Trap! ASI inserts a semicolon after return
function getSummary() {
  return
  {
    title: 'Set up the screen-printing workshop'
  };
}

console.log(getSummary()); // undefined

The engine reads return, sees the end of the line, decides the statement is complete and inserts ;. The object on the following lines is left orphaned and the function returns undefined. The fix is to put the opening brace on the same line as return.

2.2 The dangerous case: lines starting with ( or [

const ivanHours = 12
const luciaHours = 8

// This line starts with a parenthesis
;(function () {
  console.log('Independent block');
})();

Without that leading semicolon, the engine would read 8(...) as a function call on the number 8, and would throw a TypeError. The same problem happens with lines that start with [.

2.3 The recommendation

Style Advantages Drawbacks
Always writing ; Predictable, no surprises, the majority practice in the industry One extra character per line
Omitting them Code that looks slightly cleaner Requires knowing and remembering the exceptions

In this course we will always write the semicolon. It is the safe option while you are learning, and the most common one in professional teams. If one day you work on a project that omits them, a formatting tool will take care of it automatically.

  1. Blocks with braces {}

A block groups several statements so that they are treated as a unit. It is delimited with braces.

if (priority === 'high') {
  console.log('Notify the team');
  console.log('Mark it on the board');
}

Braces appear in conditionals, loops, functions and classes. Two observations for beginners:

First: if an if has a single statement, the braces are optional. But omitting them is a classic source of bugs:

// Classic trap: only the first line depends on the if
if (priority === 'high')
  console.log('Notify the team');
  console.log('This line runs ALWAYS');

The indentation suggests that both lines depend on the if, but only the first one does. Always use braces, even for a single line.

Second: blocks create scope for let and const. A variable declared inside a block does not exist outside it. It is a central idea that you will see in detail in Variables and Data Types and in depth in Scope and Closures.

{
  const note = 'Only visible inside the block';
  console.log(note); // works
}
// console.log(note); // ReferenceError: note is not defined

  1. Case sensitivity

JavaScript distinguishes uppercase from lowercase. No exceptions and no warnings.

const estimatedHours = 12;

console.log(estimatedHours); // 12
// console.log(EstimatedHours); // ReferenceError
// console.log(estimatedhours); // ReferenceError

These four spellings are four different identifiers: task, Task, TASK, tAsK.

This also affects keywords and the language's own functions:

Correct Incorrect Resulting error
console.log() Console.log() ReferenceError: Console is not defined
const Const SyntaxError
if If ReferenceError: If is not defined
Math.round() math.round() ReferenceError: math is not defined

Notice something revealing: console is lowercase but Math is capitalized. There is no logic that explains it; it is the language's history. When in doubt, check the documentation.

  1. Rules and conventions for names

An identifier is the name you give a variable, function or class. There are rules (mandatory) and conventions (industry agreements).

5.1 Mandatory rules

A valid identifier:

  • Starts with a letter, an underscore (_) or a dollar sign ($).
  • May then contain letters, digits, _ and $.
  • Cannot start with a digit.
  • Cannot contain spaces or hyphens (-).
  • Cannot be a reserved word.
// Valid
const title = 'Set up the workshop';
const hours2026 = 40;
const _internal = true;
const $element = null;

// Invalid
// const 2hours = 10;      // SyntaxError: starts with a digit
// const total-hours = 10; // SyntaxError: the hyphen is the subtraction operator
// const const = 10;       // SyntaxError: reserved word

Technically JavaScript accepts accented and non-ASCII characters (const añoInicio = 2026; works), but do not do it: it complicates collaboration, causes encoding problems and is not industry practice. Keep identifiers in plain ASCII English.

5.2 Naming conventions

Convention Appearance Used for Example in Nómada Tasks
camelCase First word lowercase, following words capitalized Variables and functions estimatedHours, dueDate, calculateWorkload
PascalCase Every word capitalized Classes and constructors Task, TaskManager
UPPER_SNAKE_CASE All uppercase, words separated by _ Fixed global constants VALID_PRIORITIES, MAX_WEEKLY_HOURS
_leadingUnderscore Starts with _ An old convention for "internal use" _internalCache

Applied to the project:

// Global configuration constant: UPPER_SNAKE_CASE
const MAX_WEEKLY_HOURS = 40;

// Regular variables: camelCase
const taskAssignee = 'Marta';
const estimatedHours = 6;
const dueDate = '2026-10-15';

5.3 Names that make sense

Conventions tell you how to write; judgment tells you what to write.

Bad name Good name Why
x estimatedHours x says nothing
d dueDate Single-letter abbreviations are forgotten
data pendingTasks "Data" describes everything and nothing
flag isCompleted Booleans read better as a statement of fact
tmp2 remainingHours Numbered names hide the meaning

Practical rule: if you need a comment to explain what a variable holds, change its name.

  1. Reserved words

These are terms with their own meaning in the language; you cannot use them as identifiers.

Category Words
Declaration var, let, const, function, class
Flow control if, else, switch, case, default, for, while, do, break, continue, return
Errors try, catch, finally, throw
Objects new, this, super, delete, in, instanceof, typeof, void
Modules import, export, from, as
Asynchrony async, await, yield
Values true, false, null
Reserved for the future enum, implements, interface, package, private, protected, public, static
// const class = 'design'; // SyntaxError
// const new = 'task';     // SyntaxError

// Correct alternatives
const category = 'design';
const newTask = 'task';

Two curious details: undefined is not a reserved word (it is a global variable, although you should never reassign it), and await is only reserved inside async functions and in modules.

  1. Whitespace, indentation and style

As far as the engine is concerned, whitespace and line breaks are irrelevant (except inside strings). These two versions are identical to JavaScript:

const t={title:'Review the invoices',assignee:'Marta',hours:3};
const t = {
  title: 'Review the invoices',
  assignee: 'Marta',
  hours: 3
};

Identical for the machine, but radically different for a human. And code is read many more times than it is written.

Common conventions:

Aspect Convention Example
Indentation 2 spaces per level console.log(x);
Spaces around operators Yes const total = a + b;
Space after commas Yes console.log(a, b, c);
Opening brace On the same line if (x) {
Space after if, for, while Yes if (priority === 'high') {
Space before the parenthesis when calling No calculateWorkload(tasks)
Line length Around 80-100 characters

Do not memorize this table: in Module 8 you will configure tools that apply the formatting automatically on save. What matters right now is that you pick a style and stick to it.

  1. Expressions versus statements

This distinction sounds theoretical and turns out to be tremendously practical.

  • An expression is a piece of code that produces a value.
  • A statement is a complete order that does something.

The definitive test: can I put this where a value is expected? If yes, it is an expression.

// Expressions: each one produces a value
12                             // the number 12
12 + 8                         // 20
'Marta'                        // the text 'Marta'
estimatedHours > 10            // true or false
'high' === 'high'              // true
calculateWorkload('Iván')      // whatever the function returns
// Statements: they are orders, not values
const assignee = 'Lucía';
if (hours > 8) { console.log('Long day'); }
for (let i = 0; i < 3; i++) { console.log(i); }

Expressions nest inside statements:

//        ┌──── declaration statement ────┐
const totalHours = 12 + 8 + 6;
//                 └── expression: 26 ──┘

Why does it matter? Because it explains what can be written where. An if is a statement, so you cannot assign it to a variable:

// const result = if (hours > 8) { 'long' } else { 'short' }; // SyntaxError

But the ternary operator is an expression, and that is why this works:

const workday = hours > 8 ? 'long' : 'normal'; // correct

You will study that operator in Basic Operators. Hold on to the idea: expressions are worth something; statements give orders.

  1. Literals

A literal is a value written directly in the code, exactly as it is.

Literal type Example Description
Numeric 12, 3.5, 1_000_000 Numbers written directly
String 'Marta', "high" Text between quotes
Template `Task for ${assignee}` Text between backticks, supports interpolation
Boolean true, false The two logical values
Null null The intentional absence of a value
Object { title: 'Review', hours: 3 } An object written directly
Array ['design', 'space'] A list written directly
Regular expression /^\d{4}-\d{2}-\d{2}$/ A text pattern
// Different literals describing a Taller Nómada task
const id = 1;                        // numeric
const title = 'Redesign the room';   // string
const isDone = false;                // boolean
const tags = ['design', 'space'];    // array
const assignedTo = null;             // null

The underscore as a thousands separator (1_000_000) is a modern convenience: the engine ignores it and the number becomes far more readable for you.

  1. strict mode

Strict mode turns on a more rigorous version of JavaScript: it turns some silent behaviors into errors and bans problematic legacy syntax.

You enable it by writing 'use strict'; as the first line of a file or of a function:

'use strict';

// From here on, the engine is more demanding
const assignee = 'Iván';

10.1 What changes

Without strict mode With strict mode
x = 5; without declaring silently creates a global variable ReferenceError: x is not defined
Assigning to something read-only fails silently Throws TypeError
this inside a standalone function is the global object this is undefined
Duplicate parameters in functions are allowed SyntaxError
Future reserved words usable as names Forbidden

The first case is the one that causes the most trouble:

'use strict';

function logTask() {
  totalHours = 12; // ReferenceError: totalHours is not defined
}
logTask();

Without strict mode, that line would create a global variable without any warning. It is a typo that can take weeks to show itself. With strict mode, the error appears instantly.

10.2 When you actually need to write it

Good news: less and less often. Strict mode is enabled automatically in two very common contexts:

  • Inside JavaScript modules (files loaded with <script type="module"> or with import/export). They are covered in Modules: Import and Export.
  • Inside the body of classes.

So the practical rule is: write 'use strict'; at the top of classic script files, and do not worry about it when you are working with modules or classes.

One detail: the directive must be literally the first statement (comments above it do not count). If you put it further down, it is ignored without warning.

  1. How a program is read from top to bottom

A JavaScript engine executes statements in the order they are written, top to bottom and left to right. Follow this program in your head before you read the result:

'use strict';

console.log('1. The program starts');         // A

const assignee = 'Marta';                     // B
console.log('2. Assignee:', assignee);        // C

const mondayHours = 3;                        // D
const tuesdayHours = 5;                       // E
const totalHours = mondayHours + tuesdayHours; // F

console.log('3. Total hours:', totalHours);   // G
console.log('4. The program ends');           // H

Output:

1. The program starts
2. Assignee: Marta
3. Total hours: 8
4. The program ends

A detail about line F: first the expressions are evaluated (mondayHours is 3, tuesdayHours is 5, the sum is 8) and only afterwards is the result assigned. Always in that order: the right-hand side is computed first, then stored on the left.

flowchart TD
    A["Line 1: initial message"] --> B["Line 2: store 'Marta'"]
    B --> C["Line 3: print the assignee"]
    C --> D["Lines 4-5: store 3 and 5"]
    D --> E["Line 6: evaluate 3 + 5 → 8<br/>and assign to totalHours"]
    E --> F["Lines 7-8: print the results"]

A practical consequence: you cannot use something before creating it. This fails:

console.log(assignee); // ReferenceError: Cannot access 'assignee' before initialization
const assignee = 'Lucía';

There is a mechanism called hoisting that does allow function declarations to be used before they appear in the code, and that explains the specific wording of that error. It is a topic with enough substance to deserve its own lesson: Hoisting and the Execution Context. For now, the safe rule is: declare before you use.

Common Mistakes and Tips

Common mistakes

  • Putting a semicolon after the closing brace of an if, for or function. It is not a serious error, but it is incorrect and gives a beginner away.
  • Omitting the braces in a single-line if. The indentation lies; the engine does not.
  • Getting the capitalization wrong. Console, a lowercase math, getElementByID instead of getElementById. They cause baffling ReferenceError or TypeError messages.
  • Using hyphens in names. total-hours is read as total - hours, a subtraction. The resulting error does not mention the hyphen at all.
  • Writing 'use strict'; in the middle of the file. It is silently ignored. It has to be the first statement.
  • Believing that indentation has meaning. In JavaScript it does not (unlike Python): indentation is only for humans. Blocks are defined by braces.
  • Single-letter names. They take two seconds to write and cost hours to decipher. Except for the i of a short loop, use full names.

Tips

  • Always write the semicolon while you are learning. It saves you from the ASI exceptions.
  • Always use the braces.
  • Leave a blank line between logical blocks. The code breathes and reads better.
  • Name things in camelCase and in a single language. Mixing taskTitle and tituloTarea in the same file is exhausting.
  • Format with Shift + Alt + F in VS Code. Well-aligned code reveals structural mistakes at a glance.
  • When you see a SyntaxError, also look at the line above the one reported. The engine spots the problem where it stops understanding the code, which is usually one line after the missing symbol.

Exercises

Exercise 1: Fix the syntax

The following snippet has six errors of syntax or convention. Find them and write the corrected version.

'use strict'

const 1title = 'Review the workshop inventory';
const estimated-hours = 4;
const ASSIGNEE = 'Lucía';
const class = 'maintenance';

if (estimated-hours > 3)
  Console.log('Long task');
  console.log('Notify Marta');

Exercise 2: Expression or statement?

Classify each snippet as an expression or a statement, and for the expressions state what value it produces:

  1. 40
  2. const maxHours = 40;
  3. estimatedHours * 2
  4. console.log('Nómada Tasks')
  5. if (status === 'done') { console.log('Completed'); }
  6. 'high' === 'low'
  7. status = 'in-progress'

Exercise 3: Name things correctly

Rewrite these names following JavaScript's rules and conventions, and explain in each case what was wrong:

  1. Estimated Hours (a variable with the hours planned for a task)
  2. 2assignee (the name of the second person assigned)
  3. due-date (the task's deadline)
  4. maximum_number_of_hours_per_week (a fixed configuration constant)
  5. task (a class that will represent a task)
  6. d (a variable holding the due date)

Solutions

Exercise 1

The six errors:

  1. 'use strict' without a semicolon (it works thanks to ASI, but it is inconsistent with the course style).
  2. 1title: an identifier cannot start with a digit.
  3. estimated-hours: the hyphen is the subtraction operator; camelCase must be used.
  4. class: a reserved word.
  5. Console.log: console is lowercase.
  6. The if without braces makes the second line run always, despite the indentation.

Corrected version:

'use strict';

const title = 'Review the workshop inventory';
const estimatedHours = 4;
const assignee = 'Lucía';
const category = 'maintenance';

if (estimatedHours > 3) {
  console.log('Long task');
  console.log('Notify Marta');
}

An additional note: ASSIGNEE in uppercase is not a syntax error, but by convention UPPER_SNAKE_CASE is reserved for global configuration constants, not for specific pieces of data.

Exercise 2

# Classification Value it produces
1 Expression (numeric literal) 40
2 Statement (declaration)
3 Expression (arithmetic) Twice estimatedHours
4 Expression (function call) undefined (it prints, but returns nothing)
5 Statement (conditional)
6 Expression (comparison) false
7 Expression (assignment) 'in-progress'

Cases 4 and 7 are the interesting ones. A function call is an expression even if the function returns nothing useful: that is why the console shows undefined below your console.log calls. And an assignment is also an expression whose value is the assigned one; that is why a = b = 5 works, even though writing it is not advisable.

Exercise 3

Original Corrected Problem
Estimated Hours estimatedHours Spaces are not allowed; camelCase on top of that
2assignee secondAssignee Cannot start with a digit
due-date dueDate The hyphen is the subtraction operator
maximum_number_of_hours_per_week MAX_WEEKLY_HOURS A fixed constant: UPPER_SNAKE_CASE, and more concise
task Task Classes use PascalCase
d dueDate A single-letter name says nothing

Conclusion

You now know the grammar of JavaScript. You know what a statement is and why you should always close it with a semicolon despite the existence of ASI; you use {} blocks correctly and you know that they create scope; it is clear to you that the language is case-sensitive; you know the rules for identifiers and the camelCase, PascalCase and UPPER_SNAKE_CASE conventions; you know what the reserved words are; you can tell expressions (which produce a value) from statements (which give an order); you recognize the different literals; you understand what strict mode turns on and where it comes enabled out of the box; and you can mentally follow the top-to-bottom execution of a program.

With this you can read code without the form distracting you. What you are missing is the content: the data. In the next lesson, Variables and Data Types, you will look in depth at how to declare variables with let and const, why var is discouraged, and what types of values exist in JavaScript: strings, numbers, booleans, undefined, null and a few more. By the end of it you will be able to model every field of a Nómada Tasks task precisely.

JavaScript Course: From Beginner to Advanced

Module 1: Introduction to JavaScript

Module 2: Control Structures

Module 3: Functions

Module 4: Objects and Arrays

Module 5: Advanced Objects and Functions

Module 6: The Document Object Model (DOM)

Module 7: Browser APIs and Advanced Topics

Module 8: Testing and Debugging

Module 9: Performance and Optimization

Module 10: JavaScript Frameworks and Libraries

Module 11: Final Project

© Copyright 2026. All rights reserved