SKU // 56

JavaScript Code Blocks

A code block is a group of statements wrapped in curly braces { }. You have been writing them in every if, loop, and function. This lesson looks at blocks directly: what they group, what they hide, and one classic bug they fix.

// What a Block Does

A block lets several statements act as one unit wherever JavaScript expects a single statement:

if (score >= 90) {                // block starts
  grade = "A";
  console.log("Excellent");
}                                  // block ends

Blocks appear with if / else, for, while, switch, try / catch, functions, and classes.

// Blocks Create Scope for let and const

let message = "outside";

{
  let message = "inside";       // a separate variable
  console.log(message);
}

console.log(message);
inside outside

Yes, a pair of braces on their own is legal. A standalone block is occasionally useful to keep temporary variables from leaking into the rest of the code.

// var Ignores Blocks

The old var keyword only respects function boundaries. It passes straight through if and loop blocks:

if (true) {
  var leaked = "I escaped";
  let kept   = "I stayed";
}

console.log(leaked);   // "I escaped"
console.log(kept);     // ReferenceError: kept is not defined
I escaped ReferenceError: kept is not defined

// Loop Blocks: A Fresh Variable Each Pass

With let, every pass through a loop gets its own brand-new copy of the counter. With var, all passes share one. This matters as soon as something runs later, like a timer:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log("var:", i), 0);
}

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log("let:", j), 0);
}
var: 3 var: 3 var: 3 let: 0 let: 1 let: 2

By the time the var timers run, the loop has finished and the single shared i is 3. Each let timer remembers its own j.

Tip
This is one of the most famous JavaScript bugs, and simply using let in for loops fixes it for good.

// Functions Are Blocks Too

Everything declared inside a function body (with any keyword) stays inside:

function setup() {
  var a = 1;
  let b = 2;
  const c = 3;
}
setup();
// a, b, and c are all unreachable here

// No Semicolon After a Block

if (ready) {
  start();
}           // no semicolon needed here

const go = function() {
  start();
};          // semicolon: this is an assignment statement that contains a function

// Indentation Shows Structure

JavaScript does not care about indentation, but people do. Indent the contents of every block one level so nesting is visible at a glance:

for (let row = 1; row <= 2; row++) {
  for (let col = 1; col <= 2; col++) {
    if (row === col) {
      console.log(`diagonal ${row},${col}`);
    }
  }
}
diagonal 1,1 diagonal 2,2
Watch out
A missing closing brace is one of the hardest errors to find, because the error message usually points to the end of the file, not to where the brace is missing. Consistent indentation makes the gap easy to spot.

// Quick Check

What does this log?

let msg = "A";
{
  let msg = "B";
}
console.log(msg);
Show answer
A. The let msg inside the standalone block is a separate variable that disappears when the block ends.

Why do the var timers in the loop all print 3?

  1. setTimeout always prints 3
  2. All passes share one i, and by the time the timers run the loop has finished with i at 3
  3. var cannot hold numbers
  4. The timers ran before the loop
Show answer
B. var ignores the loop block, so there is only one i. let creates a fresh copy for every pass, so each timer remembers its own value.

Which of these needs a semicolon after its closing brace?

  1. if (ok) { go(); }
  2. for (let i = 0; i < 3; i++) { go(); }
  3. const run = function() { go(); };
  4. function run() { go(); }
Show answer
C. A function expression is part of an assignment statement, which ends with a semicolon. Blocks belonging to if, loops, and function declarations do not.

// Try It

  1. Click Open Playground and run it. Read the error from the last line, then change let to var and run it again
  2. Run the two timer loops with its Try it Yourself button and confirm the var / let difference
  3. Declare the same variable name at three nesting levels and log it at each level
  4. Remove a closing brace from a nested loop and read where the error says the problem is
// Video Walkthroughs
Last updated: Oct 10, 2026, 12:55 AM ET