# JavaScript generator va iterator

> Iterator protokoli, Symbol.iterator, generator funksiyalar va yield, cheksiz ketma-ketlik hamda talab bo'yicha qiymat berish. Amaliy misollar bilan.

Manba: https://learncode.uz/javascript/generator-iterator/
Sana: 2026-06-07

`for...of` massiv, matn va `Map` bilan bir xil ishlaydi. Buning ortida
**iterator protokoli** turadi — va uni o'z obyektlaringizga ham qo'shish
mumkin.

## Iterator protokoli

> **Atama**
>
> **Iterator** — `next()` metodi bo'lgan obyekt. Har chaqiruvda
> `{ value, done }` qaytaradi: `value` — navbatdagi qiymat, `done` — tugadimi.
> **Iterable** — `Symbol.iterator` metodi bo'lgan obyekt; `for...of` aynan
> shuni talab qiladi.

```js
const arr = ["a", "b", "c"];

const it = arr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());
```

`for...of` aslida shu ishni bajaradi — `done: true` bo'lguncha `next()`
chaqiradi.

## Qo'lda iterator yozish

```js
const countdown = {
  startTime: 1,
  end: 4,

  [Symbol.iterator]() {
    let current = this.startTime;
    const end = this.end;

    return {
      next() {
        if (current <= end) {
          return { value: current++, done: false };
        }
        return { value: undefined, done: true };
      },
    };
  },
};

for (const n of countdown) {
  console.log(n);
}

console.log([...countdown]);
```

Endi obyekt `for...of` va [spread](https://learncode.uz/javascript/es6-sintaksis) bilan ishlaydi.
Ammo yozuv uzun — generator buni ancha qisqartiradi.

## Generator — birinchi tanishuv

```js
function* countdown() {
  yield 1;
  yield 2;
  yield 3;
}

const g = countdown();

console.log(g.next());
console.log(g.next());
console.log(g.next());
console.log(g.next());
```

> **Atama**
>
> **Generator** — `function*` bilan e'lon qilinadigan, bajarilishini
> **to'xtatib turadigan** funksiya. `yield` qiymat qaytaradi va funksiyani
> **pauza** qiladi; keyingi `next()` shu joydan davom ettiradi.

## Pauza qanday ishlaydi

```js
function* process() {
  console.log("  1-qadam boshlandi");
  yield "first";

  console.log("  2-qadam boshlandi");
  yield "second";

  console.log("  tugadi");
  return "final";
}

const g = process();

console.log("next() chaqirilmagunicha hech narsa bajarilmaydi");
console.log(g.next().value);
console.log(g.next().value);
console.log(g.next().value);
```

Funksiya tanasi `next()` chaqirilmaguncha **umuman** ishga tushmadi. Bu —
oddiy funksiyadan asosiy farq.

## Generator ham iterable

```js
function* countdown(startTime, end) {
  for (let i = startTime; i <= end; i++) {
    yield i;
  }
}

for (const n of countdown(1, 5)) {
  console.log(n);
}

console.log([...countdown(10, 13)]);
```

Yuqoridagi qo'lda yozilgan iterator bilan solishtiring — bir xil natija,
uch barobar qisqa kod.

## Obyektga qo'shish

```js
const group = {
  title: "IT-21",
  students: ["Aziz", "Dilnoza", "Bobur"],

  *[Symbol.iterator]() {
    for (const t of this.students) {
      yield this.title + ": " + t;
    }
  },
};

for (const row of group) {
  console.log(row);
}
```

## Cheksiz ketma-ketlik

Generator qiymatni **talab bo'yicha** beradi, shuning uchun cheksiz bo'lishi
mumkin:

```js
function* cheksizSanoq() {
  let n = 1;
  while (true) {
    yield n++;
  }
}

const g = cheksizSanoq();

console.log(g.next().value);
console.log(g.next().value);
console.log(g.next().value);

function* fibonacci() {
  let [a, b] = [0, 1];
  while (true) {
    yield a;
    [a, b] = [b, a + b];
  }
}

const f = fibonacci();
const firstTen = [];
for (let i = 0; i < 10; i++) firstTen.push(f.next().value);
console.log(firstTen);
```

> **Cheksiz generatorni spread qilmang**
>
> `[...cheksizSanoq()]` sahifani muzlatadi — u hech qachon tugamaydi. Cheksiz
> generatordan faqat kerakli miqdorni oling.

## Cheklovchi yordamchi

```js
function* infinite() {
  let n = 1;
  while (true) yield n++;
}

function* take(source, count) {
  let i = 0;
  for (const q of source) {
    if (i++ >= count) return;
    yield q;
  }
}

console.log([...take(infinite(), 5)]);

function* filtr(source, shart) {
  for (const q of source) {
    if (shart(q)) yield q;
  }
}

console.log([...take(filtr(infinite(), (n) => n % 3 === 0), 4)]);
```

Generatorlarni bir-biriga ulash mumkin — har biri qiymatni **kerak bo'lganda**
hisoblaydi. Massiv bilan bunday qilish uchun avval butun ro'yxatni yasash
kerak bo'lardi.

## yield* — boshqa generatorni qo'shish

```js
function* first() {
  yield 1;
  yield 2;
}

function* second() {
  yield "a";
  yield* first();
  yield "b";
}

console.log([...second()]);
```

## Generatorga qiymat berish

`next(value)` — `yield` natijasiga aylanadi:

```js
function* dialog() {
  const name = yield "Ismingiz nima?";
  const age = yield "Salom, " + name + "! Yoshingiz?";
  return name + " — " + age + " age";
}

const g = dialog();

console.log(g.next().value);
console.log(g.next("Aziz").value);
console.log(g.next(20).value);
```

Ikki tomonlama aloqa: generator qiymat beradi va qabul qiladi.

## Amaliy foyda — katta ma'lumot

```js
// Massiv: butun ro'yxat xotirada
function arrayWay(n) {
  const r = [];
  for (let i = 0; i < n; i++) r.push(i * 2);
  return r;
}

// Generator: bir vaqtda bitta qiymat
function* generatorUsul(n) {
  for (let i = 0; i < n; i++) yield i * 2;
}

console.log("Massiv uzunligi:", arrayWay(1000000).length);

let first = null;
for (const q of generatorUsul(1000000)) {
  first = q;
  break;
}
console.log("Generator faqat bittasini hisobladi:", first);
```

Birinchi usul million elementni xotirada yasadi; ikkinchisi bitta qiymat
hisoblab to'xtadi.

## Amaliy mashq

1. `arr[Symbol.iterator]()` ni qo'lda chaqirib, `next()` bilan yuring;
2. `function*` bilan uch qiymat beruvchi generator yozing;
3. `for...of` va spread bilan ishlatib ko'ring;
4. obyektga `*[Symbol.iterator]` qo'shing;
5. Fibonachchi generatorini yozib, birinchi 10 sonini oling;
6. `yield*` bilan ikki generatorni birlashtiring.

## Qisqacha xulosa

- **Iterator** — `next()` bilan `{ value, done }` qaytaruvchi obyekt.
- **Iterable** — `Symbol.iterator` bo'lgan obyekt; `for...of` shuni talab qiladi.
- **Generator** (`function*`) `yield` da to'xtaydi va `next()` da davom etadi.
- Generator tanasi `next()` chaqirilmaguncha ishga tushmaydi.
- Cheksiz ketma-ketlik yasash mumkin — qiymat talab bo'yicha hisoblanadi.
- `yield*` boshqa generatorni ichiga qo'shadi.

Keyingi darsda [funksional dasturlash](https://learncode.uz/javascript/funksional-dasturlash)
tamoyillari.
