# Generators

Generators are a special class of functions that simplify the task of writing iterators. A generator is a function that can stop midway and then continue from where it stopped.

## 1. The Concept

Normal functions run to completion. Generators allow you to pause execution and resume it later. This is useful for custom iterators, lazy evaluation, and controlling asynchronous flows.

## 2. Syntax

*   **Declaration:** Use `function*` (with an asterisk).
*   **Pause:** Use the `yield` keyword to return a value and pause execution.

```javascript
function* simpleGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

const generatorObject = simpleGenerator();

console.log(generatorObject.next()); // { value: 1, done: false }
console.log(generatorObject.next()); // { value: 2, done: false }
console.log(generatorObject.next()); // { value: 3, done: false }
console.log(generatorObject.next()); // { value: undefined, done: true }
```

## 3. How it Works

When called, a generator function does not execute its code. Instead, it returns a special object, called a **Generator Object**, which manages the execution.

*   **`next()`:** Resumes execution until the next `yield`. Returns an object `{ value: ..., done: ... }`.
*   **`value`:** The result of the expression after `yield`.
*   **`done`:** `true` if the function code has finished, otherwise `false`.

## 4. Infinite Streams

Since generators evaluate lazily (only when `next()` is called), you can create infinite loops without crashing the browser.

```javascript
function* idMaker() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
// ...
```

## 5. Two-way Communication

You can pass values *back* into the generator using `next(value)`. The value passed becomes the result of the `yield` expression.

```javascript
function* listener() {
  console.log("Start");
  const input = yield "Waiting for input...";
  console.log("Received:", input);
}

const gen = listener();
console.log(gen.next().value); // Start, "Waiting for input..."
gen.next("Hello!");            // Received: Hello!
```

## 6. `yield*` (Delegation)

You can delegate execution to another generator using `yield*`.

```javascript
function* generateSequence() {
  yield 1;
  yield 2;
}

function* generateAll() {
  yield* generateSequence();
  yield 3;
}

for (let value of generateAll()) {
  console.log(value); // 1, 2, 3
}
```

[[programming/javascript/vanilla/javascript]]
[[programming/javascript/vanilla/es6-features]]