25 август 2025

Generatorlar

Muntazam funktsiyalar faqat bitta, yagona qiymatni qaytaradi (yoki hech narsa).

Generatorlar talabga binoan bir nechta qiymatlarni, ehtimol cheksiz ko’p qiymatlarni qaytarishlari mumkin. Ular ma’lumotlar oqimlarini osongina yaratishga imkon beradigan ketma-ket saraluvchan bilan juda yaxshi ishlaydi.

Generator funktsiyalari

Generator yaratish uchun biz maxsus sintaksis konstruktsiyasiga muhtojmiz: “generator funktsiyasi” deb nomlangan function*.

Bunga o’xshaydi:

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

generateSequence() chaqirilganda, u kodni bajarmaydi. Buning o’rniga u “generator” deb nomlangan maxsus obyektni qaytaradi.

// "generator funktsiya" "generator obyektni" yaratadi
let generator = generateSequence();
alert(generator); // [object Generator]

Generator obyekti “muzlatilgan funktsiya chaqiruvi” sifatida qabul qilinishi mumkin:

Yaratilgandan so’ng, kodni bajarishning eng boshida to’xtatiladi.

Generatorning asosiy usuli next(). Chaqirilganda, u eng yaqin yield <value> ifodagacha bajarilishni davom ettiradi. Keyin ijro to’xtaydi va qiymat tashqi kodga qaytariladi.

Masalan, bu yerda biz generatorni yaratamiz va uning dastlabki qiymatini olamiz:

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

let one = generator.next();

alert(JSON.stringify(one)); // {value: 1, done: false}

next() natijasi har doim obyekt:

  • value: olingan qiymat.
  • done: false agar kod hali tugamagan bo’lsa, aks holda true.

Hozirda biz faqat birinchi qiymatni oldik:

Yana generator.next() ni chaqiraylik. U ijro etilishini davom ettiradi va keyingi yield ni qaytaradi:

let two = generator.next();

alert(JSON.stringify(two)); // {value: 2, done: false}

Va agar biz uni uchinchi marta chaqirsak, unda funktsiya tugaydigan return ifodasiga yetadi:

let three = generator.next();

alert(JSON.stringify(three)); // {value: 3, done: true}

Endi generator tugadi. Biz buni yakunlangan natija sifatida done:true va jarayonning value:3 qiymatidan ko’rishimiz kerak.

generator.next() yangi chaqiruvlari endi mantiqiy emas. Agar biz ularni qilsak, ular xuddi shu obyektni qaytaradilar: {done: true}.

Generatorni “orqaga qaytarish” imkoni yo’q. Ammo generateSequence() ni chaqirib boshqasini yaratishimiz mumkin.

Hozircha eng muhim narsani tushunish kerakki, generator funktsiyalari, odatdagi funktsiyalardan farqi o’laroq, kodni bajarmaydi. Ular “generator zavodlari” sifatida xizmat qiladi. function* ishga tushirish generatorni qaytaradi va biz undan qiymatlarni so’raymiz.

function* f(…) yoki function *f(…)?

Bu kichik diniy savol, ikkala sintaksis ham to’g’ri.

Ammo odatda birinchi sintaksisga afzallik beriladi, chunki * yulduzi bu generator funktsiyasi ekanligini anglatadi, u ismni emas, balki turini tavsiflaydi, shuning uchun u function kalit so’ziga ulanishi kerak.

Generatorlar ketma-ket saraluvchandir

Ehtimol, next() usulini ko’rib chiqishni taxmin qilganingizdek, generatorlar ketma-ket saraluvchan.

Biz qiymatlar bo’yicha for..of orqali tsiklashimiz mumkin:

function* generateSequence() {
  yield 1;
  yield 2;
  return 3;
}

let generator = generateSequence();

for(let value of generator) {
  alert(value); // 1, then 2
}

Bu generatorlar bilan ishlashning .next().value