Statements

Expressions are JavaScript phrases, while statements are JavaScript sentences. JavaScript statements are terminated with semicolons. Expressions are evaluated to produce a value, and statements are executed to make something happen. JavaScript program is a sequence of statements to execute.

Compound statement

A statement block {} combines multiple statements into a single compound statement. It can be used when JavaScript expects a single statement. The block does not end with a semicolon. The scope of the variables defined in a statement block is the block itself.

{
  let a = 'hello';
  a += ' there';
}

Empty statement

The empty statement ; is used when a statement is expected but you don't want to include one.

let arr = [1, 2, 3];
for (let i=0; i<arr.length; arr[i++]=0) ;

Conditional statements

The if statement is the fundamental control statement that allows JavaScript programs to make decisions based on a condition.

let n = 4;
if (n === 1) {
  // Execute code block #1
} else if (n === 2) {
  // Execute code block #2
} else if (n === 3) {
  // Execute code block #3
} else {
  // If all else fails, execute code block #4
}

The switch statement compares a variable or value to multiple values with strict equality operator === to simplify multi-branch if statements. The break keyword jumps to the end of the switch statement after executing the code block of matched case. Each case keyword can be followed by an arbitrary expression.

switch (n) {
  case 1:
    // Execute code block #1
    break;
  case 2:
    // Execute code block #2
    break;
  case 3:
    // Execute code block #3
    break;
  default:
    // Execute code block #4
}

Loops

The basic JavaScript loop is the while loop. It evaluates the condition expression which determines whether the loop should be executed or not. If the expression evaluates to true, the body of the loop is executed once and then the conditional expression is checked again. Otherwise it skips the body of the loop and moves to the next statement in the program.

let count = 0;
while (count < 3) {
  console.log(`while loop: ${count}`);
  count++;
}

The do/while loop tests for the loop conditional at the bottom of the loop, thus the body of the loop is always executed at least once. Note that the do/while loop must be terminated with a semicolon.

do {
  console.log(`do while loop: ${count}`);
} while (count < 3);

The for loop is a more convenient looping construct, providing interface for initialization, test, and increment expressions of the looping variable in its body. The scope of the variables initialized in the for loop is contained inside its body.

for (let i=0; i<3; i++) {
  console.log(`for loop: ${i}`);
}

The for/of loop is used with iterable objects like arrays, strings, sets and maps.

// Iterate over arrays
let myArr = [1, 2, 3], sum = 0;
for (let element of myArr) {
  sum += element;
}

// Iterate over object's keys
let o = { x: 1, y: 2 };
for (let k of Object.keys(o)) {
  console.log(k);
}

// Iterate over object's values
for (let v of Object.values(o)) {
  console.log(v);
}

// Iterate over object's keys and values
for (let [k, v] of Object.entries(o)) {
  console.log(k, v);
}

// Iterate over string characters
let myText = 'I\u{1F49E}\u{1F436}'; // => 'IğŸ’žğŸ¶'
myText.length // => 5
for (let char of myText) {
  console.log(char);
}

// Iterate over sets
let mySet = new Set(['hi', 'hi', 'there']);
for (let element of mySet) {
  console.log(element);
}

// Iterate over maps
let myMap = new Map([[1, 'one'], [2, 'two']]);
for (let [key, value] of myMap) {
  console.log(key, value);
}

Jumps

Labeled statements are used with break and continue statements. The namespace for labels is different than the namespace for variables and functions, so you can reuse the same name for labels that are given to variables and functions. Any two statements may have the same label if neither one is nested within the other. A statement may have multiple labels.

mainloop: for (let i=0; i<3; i++) {
  for (let j=0; j<3; j++) {
    if (i +j > 2) break mainloop;
    console.log(`Labeled for loop: ${i} ${j}`);
  }
}

The break statement causes the innermost enclosing loop or switch statement to exit immediately. When break is used with a label, it terminates the enclosing statement with that label.

for (let i=-5; i<5; i++) {
  if (i >= 0) break;
  console.log(`Negative numbers with break: ${i}`);
}

The continue statement restarts the loop at the next iteration. When continue is used with a label, it restarts the loop of enclosing statement with that label at the next iteration. Next iteration in a while loop means jumping to the evaluation of condition expression, whereas in a for loop it means jumping to the evaluation of increment and test expressions before starting the loop body.

for (let i=0; i<10; i++) {
  if (i%2) continue;
  console.log(`Even numbers with continue: ${i}`);
}

The return statement can be used only within the body of a function. When return statement is executed, the function that contains it returns the value of the expression that follows return statement.

function square(x) { return x*x; }
square(2); // => 4

The throw statement signals that an exception has occurred. Typically, throw statement is followed by an Error object, but you can also use it with a number that represents error code or a string with error message. When an exception is thrown, the execution of the program stops immediately and jumps to the nearest exception handler try/catch/finally statement. If there is no exception handler in the code block, exceptions propagate up through the call stack.

function factorial(x) {
  if (x < 0) throw new Error('x must not be negative!');
  let f;
  for (f=1; x>1; f *= x, x--) /* empty */ ;
  return f;
}

The try/catch/finally statement is the JavaScript's exception handling mechanism. The try clause defines the block of code whose exceptions must be handled. The catch clause contains an optional block of statements that is invoked when an exception occurs within the try block. An identifier in parentheses after the catch keyword refers to the associated value of the exception. The finally block contains an optional cleanup code that is guaranteed to be executed, regardless of what happens in the try block.

try {
  let x = -4;
  console.log(factorial(x));
} catch(e) {
  console.log('An error has occurred.', e.message);
} finally {
  // optional cleanup code
}