Iterator protokoli ({value, done}), Generator funksiyalar (function*), yield kalit so'zi, for...of bilan integratsiya, lazy evaluation va cheksiz (infinite) generatorlar.
Bu — kitobdagi eng murakkab va noodatiy mavzulardan biri. Generator'lar JavaScript'ga function'larning ishlashini "pauza qilish" va "davom ettirish" imkonini beradi — bu boshqa hech qanday oddiy function'da mavjud bo'lmagan xususiyat.
Iterator — to'plam (masalan, array)ning elementlarini birma-bir, tartib bilan "aylanib chiqish" imkonini beruvchi maxsus object.
Chapter 5'da for...of loop'ni ko'rgan edik — u array, string kabi narsalar ustida ishlaydi. Buning "sahna orqasida" — bu narsalar Iterable protokoliga amal qilgani uchun ishlaydi, va bu protokolning asosini Iterator tashkil qiladi.
Iterator — next() nomli metodga ega bo'lgan har qanday object, bu metod har chaqirilganda { value, done } shaklidagi object qaytaradi.
script.jsJavaScriptfunction createIterator(array) {let index = 0;return {next: function () {if (index < array.length) {return { value: array[index++], done: false };} else {return { value: undefined, done: true };}}};}let iterator = createIterator(["a", "b", "c"]);console.log(iterator.next()); // { value: "a", done: false }console.log(iterator.next()); // { value: "b", done: false }console.log(iterator.next()); // { value: "c", done: false }console.log(iterator.next()); // { value: undefined, done: true }
Har safar next() chaqirilganda, u keyingi elementni qaytaradi va indexni oshiradi. done: true — barcha elementlar tugaganini bildiradi.
💡 Key Idea
for...of loop (Chapter 5) — aslida sahna orqasida shu next() metodini avtomatik, done: true bo'lguncha, ketma-ket chaqirib turadi.
Generator Function — Iterator yaratishning ancha oson, o'qish qulay usuli. U function* (yulduzcha bilan) yoziladi va yield kalit so'zi orqali qiymatlarni "birma-bir chiqarib beradi".
Chunki generator function — oddiy function'lardan tubdan farq qiladi: u chaqirilganda darhol ishlamaydi, balki "pauza qila oladigan" maxsus object (generator object) qaytaradi.
⏸️▶️ Oddiy function — bu filmni "Play" tugmasi bosilgach, oxirigacha to'xtovsiz ko'rsatadigan pleer. Generator function esa — "Pauza" tugmasi ham bor pleer: siz filmni istalgan joyda to'xtatib, keyinroq aynan o'sha joydan davom ettirishingiz mumkin.
script.jsJavaScriptfunction* simpleGenerator() {console.log("Boshlandi");yield 1;console.log("Birinchi yield'dan keyin");yield 2;console.log("Ikkinchi yield'dan keyin");yield 3;console.log("Tugadi");}let gen = simpleGenerator();console.log(gen.next()); // "Boshlandi" chiqadi, { value: 1, done: false }console.log(gen.next()); // "Birinchi yield'dan keyin" chiqadi, { value: 2, done: false }console.log(gen.next()); // "Ikkinchi yield'dan keyin" chiqadi, { value: 3, done: false }console.log(gen.next()); // "Tugadi" chiqadi, { value: undefined, done: true }
simpleGenerator() chaqirilganda, function ichidagi kod darhol ishlamaydi — faqat "generator object" qaytariladi.gen.next() chaqirilganda, kod ishga tushadi va birinchi yield 1gacha bajariladi, o'sha yerda "pauza" qiladi, { value: 1, done: false } qaytaradi.gen.next() — funksiya to'xtagan joyidan davom etadi (birinchi yielddan keyingi qatordan), ikkinchi yield 2gacha ishlaydi.done: true qaytarilguncha) davom etadi.code.textTEXTsimpleGenerator() chaqiriladi → generator object yaratiladi (hali ishlamaydi)next() #1 → "Boshlandi" → yield 1 da PAUZA → { value: 1, done: false }next() #2 → davom etadi → "Birinchi yield'dan keyin" → yield 2 da PAUZA → { value: 2, done: false }next() #3 → davom etadi → "Ikkinchi yield'dan keyin" → yield 3 da PAUZA → { value: 3, done: false }next() #4 → davom etadi → "Tugadi" → function tugaydi → { value: undefined, done: true }
🔥 Important
Bu — oddiy function'da mutlaqo mumkin bo'lmagan xususiyat: oddiy function chaqirilganda, u to'liq bajarilmaguncha "to'xtay olmaydi". Generator esa o'z holatini "eslab qolib", xohlagan joyda pauza qilib, keyin davom etishi mumkin.
Generator'lar avtomatik ravishda Iterable hisoblanadi, shuning uchun ularni to'g'ridan-to'g'ri for...of bilan aylanib chiqish mumkin (next()ni qo'lda chaqirmasdan).
script.jsJavaScriptfunction* countTo(max) {for (let i = 1; i <= max; i++) {yield i;}}for (let num of countTo(5)) {console.log(num);}// 1, 2, 3, 4, 5
for...of — sahna orqasida next()ni avtomatik, done: true bo'lguncha chaqiradi, aynan Chapter 40.1'dagi qo'lda yozilgan Iterator kabi, lekin bu safar Generator sintaksisi orqali ancha oson yozilgan.
Generator'larning eng kuchli xususiyatlaridan biri — ular cheksiz ketma-ketlik yaratishi mumkin, chunki qiymatlar faqat kerak bo'lganda, birma-bir hisoblanadi (bu — "lazy evaluation" deb ataladi).
Agar cheksiz array yaratishga urinilsa ([1, 2, 3, ...] — cheksiz), dastur xotirasi darhol tugaydi. Lekin Generator — hech qachon "hammasini bir vaqtda" hisoblamaydi, u faqat so'ralganda, bittadan qiymat beradi.
script.jsJavaScriptfunction* infiniteNumbers() {let num = 1;while (true) {yield num;num++;}}let numbers = infiniteNumbers();console.log(numbers.next().value); // 1console.log(numbers.next().value); // 2console.log(numbers.next().value); // 3// ... va h.k., abadiy davom etishi mumkin, lekin xotira TUGAMAYDI
while (true) — odatda cheksiz loop yaratib, dasturni "osilib qoldiradi" (Chapter 5'da ko'rgan edik). Lekin Generator ichida bu xavfsiz, chunki loop faqat har yieldda "pauza" qiladi va tashqaridan next() chaqirilmaguncha hech narsa qilmaydi.
💡 Key Idea
Bu — "lazy evaluation" (dangasa hisoblash) tamoyilining amaliy namunasi: qiymatlar faqat aniq kerak bo'lgan paytda hisoblanadi, oldindan emas. Bu — katta yoki cheksiz ma'lumotlar bilan ishlashda xotirani tejashning kuchli usuli.
script.jsJavaScriptfunction take(generator, count) {let results = [];for (let i = 0; i < count; i++) {results.push(generator.next().value);}return results;}console.log(take(infiniteNumbers(), 5)); // [1, 2, 3, 4, 5]
yield — nafaqat qiymat "chiqarib berishi", balki next() chaqirilganda tashqaridan qiymat qabul qilishi ham mumkin.
script.jsJavaScriptfunction* chatBot() {let name = yield "Ismingiz nima?";let age = yield `Salom, ${name}! Necha yoshdasiz?`;return `${name}, ${age} yoshda ekansiz. Xayr!`;}let bot = chatBot();console.log(bot.next().value); // "Ismingiz nima?"console.log(bot.next("Ali").value); // "Salom, Ali! Necha yoshdasiz?"console.log(bot.next(25).value); // "Ali, 25 yoshda ekansiz. Xayr!"
bot.next("Ali") — bu qiymat ("Ali") generator ichidagi kutib turgan yield "Ismingiz nima?" ifodasining natijasi sifatida name variable'iga o'tadi. Bu — generator va tashqi kod orasida ikki tomonlama muloqot imkonini beradi.
🔗 Connection
Bu mexanizm — Chapter 28'da o'rgangan async/awaitning ichki ishlash tamoyiliga juda o'xshaydi. Aslida, async/await — Generator'lar va Promise'larning kombinatsiyasi asosida qurilgan (bu — ilg'or, ixtiyoriy bilim, kundalik dasturlashda buni bilish shart emas).
Task:
function* colors() nomli generator yozing, u ketma-ket "qizil", "yashil", "ko'k" qiymatlarini yield qilsin. for...of bilan barchasini chiqaring.
Required Concepts:
yieldyield "qizil"; yield "yashil"; yield "ko'k";Task:
function* range(start, end) nomli generator yozing — u startdan endgacha (ikkalasi ham kiritilgan) barcha sonlarni birma-bir yield qilsin. for...of bilan sinab ko'ring.
Required Concepts:
yield i qiling.Task:
Cheksiz Fibonacci ketma-ketligi generatorini yozing (function* fibonacci()), u 0, 1, 1, 2, 3, 5, 8, ... tartibida cheksiz davom etsin. Chapter 40.4'dagi take() function yordamida, faqat birinchi 10 ta Fibonacci sonini array sifatida oling.
Required Concepts:
let [prev, curr] = [0, 1]; while(true) { yield prev; [prev, curr] = [curr, prev + curr]; }script.jsJavaScriptfunction* gen() {yield 1;yield 2;return 3;yield 4; // bu qatorga yetib bo'lamizmi?}let g = gen();console.log(g.next());console.log(g.next());console.log(g.next());console.log(g.next());
🧠 Think first! Javobni ko'rishdan oldin kamida 30 soniya o'ylang.
<details> <summary>Answer</summary> { value: 1, done: false } { value: 2, done: false } { value: 3, done: true } { value: undefined, done: true }Why?
return 3 — generator'ni darhol tugatadi (done: true bilan), xuddi oddiy function'dagi return kabi (Chapter 6). Shuning uchun yield 4 qatoriga hech qachon yetib bo'linmaydi. To'rtinchi next() chaqirilganda, generator allaqachon "tugagan", shuning uchun u doimiy ravishda { value: undefined, done: true } qaytaraveradi.
Quyidagi kodda muammo bor:
script.jsJavaScriptfunction* countdown(start) {while (start > 0) {yield start;start--;}}let counter = countdown(3);console.log(counter.value); // dasturchi "3" kutgan, lekin undefined chiqadi
Your Task:
counter.value undefined ekanini tushuntiring.Yechim:
</details>script.jsJavaScriptlet counter = countdown(3);console.log(counter.next().value); // 3console.log(counter.next().value); // 2console.log(counter.next().value); // 1
next() metodiga ega, { value, done } qaytaradigan object.function*) — Iterator yaratishning oson, "pauza qila oladigan" usuli.yield — qiymatni "chiqarib berish" va function'ni pauza qilish uchun ishlatiladi.next(value) — generator ichidagi kutib turgan yieldga qiymat "yuborish" imkonini beradi.next() chaqiruvi — keyingi yieldgacha kodni davom ettiradi.for...of — generator'lar bilan avtomatik, next()ni qo'lda chaqirmasdan ishlaydi.script.jsJavaScriptfunction* myGenerator() {yield 1;yield 2;yield 3;}let gen = myGenerator();gen.next(); // { value: 1, done: false }for (let value of myGenerator()) {console.log(value);}function* infinite() {let i = 0;while (true) yield i++;}
Mavzu bo‘yicha tushunchalaringizni interaktiv test orqali sinovdan o‘tkazing va natijalarni bilib oling.
Darslikda o‘rganilgan qoidalarga asosan real kod yozing, testlardan o‘tkazing va yechimlarni mustahkamlang.
Test Sinovi
Hali topshirilmagan (kamida 75% kerak)
Amaliy Masalalar
0 / 3 ta yechildi (kamida 75% kerak)
Dars sifati va mazmunini yaxshilash uchun o‘z haqqoniy bahoingizni qoldiring.
Mavzuni to‘liq o‘zlashtirish uchun test sinovi, amaliy kodlash va bog‘liq darslar
O‘z bilimingizni interaktiv test savollari orqali tekshiring va darhol xatolarni tahlil qiling.
Nazariyani real kod yozish bilan mustahkamlang, avtomatik testlardan o‘ting va XP to‘plang.
Kurs bo‘yicha keyingi va bog‘liq mavzular: