Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

The for...of statement executes a loop that operates on a sequence of values sourced from an iterable object. Rather than iterating over object keys or maintaining a manual counter, it consumes the JavaScript iterable protocol, extracting values directly from objects that implement the [Symbol.iterator]() method.
for ([const | let | var] variable of iterable) {
  // statement
}

Technical Mechanics

Under the hood, the for...of loop abstracts the manual consumption of an iterator. When the loop initializes, it performs the following sequence:
  1. Protocol Invocation: It calls the [Symbol.iterator]() method on the iterable object to retrieve an iterator object. If the object is not iterable (e.g., a plain Object), a TypeError is thrown.
  2. Iteration: It repeatedly calls the next() method on the retrieved iterator.
  3. Type Validation: It strictly enforces that the value returned by next() is an Object. If next() returns a primitive, a TypeError is thrown.
  4. Value Binding: It extracts the value property from the returned IteratorResult object ({ value: any, done: boolean }) and assigns it to the variable.
  5. Termination: The loop terminates automatically when the IteratorResult object returns done: true.
To illustrate the underlying mechanics—including how it handles continue directives, strict object return types, early termination, and IteratorClose exception precedence—a for...of loop is functionally equivalent to the following manual iteration:
const iterator = iterable[Symbol.iterator]();
let isNormalCompletion = true;
let didThrow = false;
let loopError;

try {
  while (true) {
    const result = iterator.next();
    
    // Standard semantics require next() to return an Object
    if (Object(result) !== result) {
      throw new TypeError("Iterator result is not an object");
    }
    
    isNormalCompletion = result.done;
    if (isNormalCompletion) {
      break;
    }
    
    const variable = result.value;
    // statement (a `continue` here safely jumps to the next while iteration)
  }
} catch (err) {
  didThrow = true;
  loopError = err;
} finally {
  // Triggers the IteratorClose protocol only on abrupt completion of the loop body
  // (e.g., break, return, or a throw inside the block).
  try {
    if (!isNormalCompletion && typeof iterator.return === 'function') {
      const returnResult = iterator.return();
      
      // Standard semantics require return() to return an Object
      if (Object(returnResult) !== returnResult) {
        throw new TypeError("Iterator result is not an object");
      }
    }
  } catch (returnErr) {
    // If the loop body threw an exception, it takes precedence over a return() exception.
    if (!didThrow) {
      throw returnErr;
    }
  }
  
  // Propagate the original loop body exception
  if (didThrow) {
    throw loopError;
  }
}

Variable Declaration and Scoping

The variable in the loop signature is typically declared using const, let, or var, which dictates its binding behavior across iterations:
  • const: Creates a new, immutable lexical binding for each iteration. The variable cannot be reassigned within the loop body. This is the standard recommendation unless reassignment is required.
  • let: Creates a new, mutable lexical binding for each iteration.
  • var: Creates a single binding scoped to the enclosing function or global execution context. The same variable is mutated on each iteration, which can lead to unintended side effects if referenced asynchronously inside the loop.
  • Assignment to an existing variable/property: You can omit the declaration keyword entirely to assign the yielded value to an existing, previously declared variable in the current scope, or to an object property (e.g., for (obj.prop of iterable)).

Control Flow and Early Termination

The loop supports standard control flow statements: break, continue, return, and throw. If a for...of loop body results in an abrupt completion (via break, return, or an uncaught exception inside the block), it triggers the IteratorClose protocol. As shown in the manual equivalent above, the engine will automatically call the return() method on the iterator object (if it exists). This allows the iterable to perform necessary cleanup operations, such as closing file handles or releasing network sockets, before the execution context shifts. According to the ECMAScript specification, IteratorClose is only triggered if the loop body itself causes the abrupt completion. If the iterator’s next() method throws an exception, the iterator is already considered closed or abrupt, and return() is not invoked. Furthermore, if both the loop body and the iterator.return() method throw exceptions, the original exception from the loop body takes precedence and is propagated, while the return() exception is swallowed.

Asynchronous Iteration

JavaScript provides the for await...of variant to handle asynchronous iteration. This statement must be executed within an async function or at the top level of a module (top-level await); attempting to use it in a standard synchronous context throws a SyntaxError.
for await ([const | let | var] variable of iterable) {
  // statement
}
This variant primarily consumes objects implementing the async iterable protocol ([Symbol.asyncIterator]()), awaiting the resolution of the Promise returned by the async iterator’s next() method before executing the loop body. Additionally, for await...of accepts standard synchronous iterables. If the provided object does not implement [Symbol.asyncIterator]() but does implement [Symbol.iterator](), the loop falls back to the synchronous iterator. It passes each synchronously yielded value through Promise.resolve(). Consequently, if the synchronous iterable yields a pending Promise, the loop will pause and wait for that Promise to resolve before assigning the resolved value to the variable and executing the loop body.
Master JavaScript with Deep Grasping Methodology!Learn More