Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. Birinchi zanjir
- 2.1 values() dan boshlanadi
- 2.2 Massivdan to'g'ridan-to'g'ri — yo'q
- 3. Dangasa: konveyer tartibi
- 3.1 Callback'lar qaysi tartibda chaqiriladi?
- 3.2 Qadamma-qadam
- 3.3 O'lchaymiz: 1000 buyurtmadan birinchi uchta
- 4. Metodlar oilasi
- 4.1 Ikki tur: zanjirni davom ettiruvchi va tugatuvchi
- 4.2 Callback imzosi boshqacha
- 4.3 flatMap — faqat iterable qaytaring
- 5. Cheksiz ketma-ketliklar bilan
- 6. Ichidan: helper'ni generator bilan yozamiz
- 7. Iterator.from() — o'z iteratoringizga helper'lar
- 7.1 Qo'lda yozilgan iteratorda metod yo'q
- 7.2 Iterator.from o'rab beradi
- 8. Qayerda ishlaydi: Baseline va Node
- 9. Qachon massiv, qachon iterator helper?
- 10. Ko'p uchraydigan xatolar
- 10.1 toArray() ni unutish
- 10.2 Massivda take / drop ni chaqirish
- 10.3 Zanjirni ikki marta ishlatish
- 10.4 flatMap dan satr qaytarish
- 10.5 Bo'sh iteratorda boshlang'ichsiz reduce
- 10.6 take ga noto'g'ri son
- 11. Mashqlar
- 1-mashq (oson): Arzon taomlar
- 2-mashq (o'rta): Bo'sh bron vaqtlari
- 3-mashq (qiyin): O'z Iterator.concat ingiz
- 4-mashq: Vazifalar qadami — helper'lar royxat ustida (mashqlar repo)
- 12. Real ishda
- Xulosa
- Manbalar
JavaScript iterator helpers (ES2025): map, filter, take dangasa ishlaydi
Qisqacha: ES2025 dan boshlab har bir o'rnatilgan iteratorda — massiv
values()si,Map/Setiteratorlari, generatorlar — massivdagiga o'xshash metodlar bor:map,filter,take,drop,flatMap,reduce,toArray,some,every,find,forEach. Ular oraliq massiv yasamaydi va dangasa ishlaydi: qiymatlar zanjir bo'ylab bittadan o'tadi va faqat so'ralganda. Shuning uchuntake(3)cheksiz ketma-ketlikda ham ishlaydi. O'z iteratoringizga bu metodlarniIterator.from()beradi.
Bu darsda
- Iterator helpers zanjirini yozasiz:
menyu.values().filter(...).map(...).toArray(). - Massiv zanjiri va iterator zanjiri callback'larni qaysi tartibda chaqirishini ko'rasiz va farqini o'lchaysiz.
- O'zgartiruvchi (
map,filter,take,drop,flatMap) va yakunlovchi (toArray,reduce,find…) metodlarni ajratasiz. Iterator.from()bilan o'z iteratoringizga helper'larni qo'shasiz.- Brauzer va Node qo'llovini (Baseline) tekshirib, massiv yoki iterator helper'ni ongli tanlaysiz.
Oldin bilishingiz kerak: Metod zanjiri va ma'lumot pipeline, Generator funksiyalar, Generatorlar chuqur, Map, Callback imzosi.
1. Nega bu kerak?
Metod zanjiri darsida va'da bergan edik: "2025-yilda JavaScript'ga dangasa zanjir ham qo'shildi — buyurtmalar.values().filter(...).take(3).toArray()". Bugun shu va'dani bajaramiz.
Avval massiv zanjirining ikki noqulayligini eslaymiz.
Birinchi: u hammasini qiladi. «Bahor»da bugun 1000 ta buyurtma bo'ldi. Jasur aka so'radi: "30 000 so'mdan qimmat birinchi uchta buyurtma qaysi?" Massiv bilan:
const narxlar = [5000, 28000, 35000, 30000, 63000];
const buyurtmalar = Array.from({ length: 1000 }, (_, i) => ({
id: i + 1,
summa: narxlar[i % 5],
}));
let tekshirildi = 0;
const birinchiUch = buyurtmalar
.filter((b) => {
tekshirildi++;
return b.summa > 30000;
})
.map((b) => b.id)
.slice(0, 3);
console.log(birinchiUch); // [ 3, 5, 8 ]
console.log(tekshirildi); // 1000Javob uchun sakkizta buyurtmani ko'rish kifoya edi. filter esa mingtasini tekshirdi, 400 ta mos keluvchidan yangi massiv yasadi, map ularning hammasidan yana bitta massiv yasadi. slice esa oxirida 397 tasini tashlab yubordi.
Ikkinchi: u faqat massivda. Map, Set, generator — massiv emas. Ularda filter yo'q. Avval [...] bilan massivga aylantirish kerak, cheksiz generatorni esa umuman aylantirib bo'lmaydi (Generator funksiyalar).
Iterator helpers ikkala muammoni yopadi. O'xshatish: konveyer. Massiv zanjiri — har bosqich butun partiyani tugatib, keyingi bosqichga yashik bilan uzatadigan sex. Iterator zanjiri — konveyer lentasi: har mahsulot bittadan barcha bosqichlardan o'tadi, va "uchta tayyor" bo'lishi bilan lenta to'xtaydi.
2. Birinchi zanjir
2.1 values() dan boshlanadi
const menyu = new Map([
["osh", 35000],
["lag'mon", 28000],
["manti", 30000],
["ko'k choy", 5000],
]);
const arzonlar = menyu
.entries()
.filter(([taom, narx]) => narx < 31000)
.map(([taom]) => taom);
console.log(arzonlar);
console.log(arzonlar.toArray());Konsolda:
Object [Iterator Helper] {}
[ "lag'mon", 'manti', "ko'k choy" ]Qatorma-qator:
menyu.entries()—Mapiteratori, u[kalit, qiymat]juftliklarini beradi (Iteratsiya protokoli)..filter(...)— massivniki emas, iteratorning metodi. U massiv emas, yangi iterator qaytaradi..map(...)— yana yangi iterator.console.log(arzonlar)—Object [Iterator Helper] {}. Bu hali natija emas, faqat "tayyor zanjir". Hech bir callback hali chaqirilmagan!.toArray()— zanjirni ishga tushiradi va qiymatlarni massivga yig'adi.
Iterator helpers (inglizcha "iterator yordamchilari") — ES2025 standartida iteratorlarga qo'shilgan metodlar to'plami. Ular hamma o'rnatilgan iteratorlarning umumiy ajdodida — Iterator.prototype da turadi (Prototip zanjiri). Shuning uchun massiv, Map, Set, satr iteratorlari va generatorlar — hammasi ularni meros oladi.
2.2 Massivdan to'g'ridan-to'g'ri — yo'q
const narxlar = [35000, 28000];
narxlar.take(1);Konsolda:
TypeError: narxlar.take is not a functionTarjimasi: "narxlar.take — funksiya emas". Massivning o'zi iterator emas — unda take yo'q. Iterator helper kerak bo'lsa, avval iterator oling: narxlar.values().take(1). map va filter esa massivda ham bor — lekin bu boshqa metodlar: massivniki darhol massiv qaytaradi, iteratorniki — dangasa iterator.
Tekshirib ko'ring:
new Set(["osh", "manti"]).values().map((t) => t.length)nima qaytaradi?.toArray()qo'shilsa-chi?
Javob
Birinchisi — Object [Iterator Helper] {}: zanjir tayyor, lekin hali ishlamagan. .toArray() bilan — [ 3, 5 ]. Set iteratori ham Iterator.prototype dan meros oladi, shuning uchun unda ham map bor — [...to'plam] bilan massivga aylantirish shart emas.
3. Dangasa: konveyer tartibi
3.1 Callback'lar qaysi tartibda chaqiriladi?
Ikkala zanjirga "gapiradigan" callback'lar beramiz:
const taomlar = [
{ nom: "osh", narx: 35000 },
{ nom: "choy", narx: 5000 },
{ nom: "manti", narx: 30000 },
];
const katta = (t) => {
console.log(`filter: ${t.nom}`);
return t.narx > 10000;
};
const nomi = (t) => {
console.log(`map: ${t.nom}`);
return t.nom;
};
taomlar.filter(katta).map(nomi);
console.log("---");
taomlar.values().filter(katta).map(nomi).toArray();Konsolda:
filter: osh
filter: choy
filter: manti
map: osh
map: manti
---
filter: osh
map: osh
filter: choy
filter: manti
map: mantiMassiv zanjiri — bosqichma-bosqich: avval filter hamma elementni o'tkazdi, keyin map natijani. Iterator zanjiri — elementma-element: osh filter dan o'tib, darhol map ga bordi; choy filter da to'xtadi va map ga yetmadi; keyin manti. Bu Generator funksiyalar darsidagi "oshxona va ofitsiant"ning o'zi.
3.2 Qadamma-qadam
Keyingi ni bosing va next() so'rovi zanjir bo'ylab qanday "orqaga" yurishini kuzating: oxirgi bo'g'in oldingisidan so'raydi, u esa o'zidan oldingisidan.
Dangasa hisob — o'tgan darslardagi atama: qiymat faqat so'ralganda hisoblanadi. Zanjir yasash — tekin; ish faqat iste'molchi (next(), toArray(), for...of) so'raganda boshlanadi.
3.3 O'lchaymiz: 1000 buyurtmadan birinchi uchta
«Nega bu kerak?» bo'limidagi savolni iterator zanjiri bilan:
const narxlar = [5000, 28000, 35000, 30000, 63000];
const buyurtmalar = Array.from({ length: 1000 }, (_, i) => ({
id: i + 1,
summa: narxlar[i % 5],
}));
let tekshirildi = 0;
const birinchiUch = buyurtmalar
.values()
.filter((b) => {
tekshirildi++;
return b.summa > 30000;
})
.map((b) => b.id)
.take(3)
.toArray();
console.log(birinchiUch); // [ 3, 5, 8 ]
console.log(tekshirildi); // 8Natija bir xil, lekin filter 1000 emas, 8 marta chaqirildi. take(3) uchinchi qiymatni olgach, zanjirga "boshqa kerak emas" dedi va hamma bo'g'in to'xtadi. Oraliq massivlar ham yo'q.
Vaqtda bu qanday ko'rinadi? Million buyurtmada ikki vazifani o'lchadik: "birinchi uchta" va "hammasining summasi" (filter → map → reduce):
- Massiv: birinchi 3hammasini filtrlaydi43,7 ms
- Iterator: birinchi 30,1 ms dan kam0 ms
- Massiv: hammasi2 oraliq massiv65,4 ms
- Iterator: hammasioraliq massivsiz81,2 ms
Manba: O'lchov: Node 24.21, Windows 11, performance.now, 9 o'lchovning medianasi, 2026-10-04
Ikki xulosa. "Birinchi N ta" yoki "birinchi mos keluvchi" kerak bo'lsa — iterator zanjiri yuzlab marta tezroq: u ishni erta to'xtatadi. Hamma element kerak bo'lsa — oddiy massiv zanjiri biroz tezroq: har qiymatning zanjir bo'ylab "so'rov-javob" yurishi ham vaqt oladi. Dangasalik tekin emas — u faqat ishni tejash mumkin bo'lganda yutadi.
Tekshirib ko'ring:
buyurtmalar.values().filter(...).map(...)zanjirini yasab,toArray()ni chaqirmasak,tekshirildinechaga teng bo'ladi?
Javob
0. Zanjir yasash hech qanday callback'ni chaqirmaydi — u faqat iteratorlarni bir-biriga ulaydi. Callback'lar faqat kimdir qiymat so'raganda (next(), toArray(), for...of, spread) ishlaydi.
4. Metodlar oilasi
4.1 Ikki tur: zanjirni davom ettiruvchi va tugatuvchi
| O'zgartiruvchi (yangi iterator) | Nima qiladi |
|---|---|
map(fn) |
har qiymatni fn bilan o'zgartiradi |
filter(fn) |
fn rost qaytarganlarini o'tkazadi |
take(n) |
birinchi n tasini beradi, keyin to'xtaydi |
drop(n) |
birinchi n tasini tashlab, qolganini beradi |
flatMap(fn) |
fn qaytargan iterable'ni ochib, bittadan beradi |
| Yakunlovchi (natija) | Nima qaytaradi |
|---|---|
toArray() |
hamma qiymatlar massivi |
reduce(fn, boshlang'ich) |
bitta yig'ma qiymat |
some(fn), every(fn) |
true / false |
find(fn) |
birinchi mos qiymat yoki undefined |
forEach(fn) |
undefined (faqat yon ta'sir uchun) |
O'zgartiruvchilar zanjir quradi va hech narsa hisoblamaydi. Yakunlovchilar zanjirni "yoqadi" va iteratorni oxirigacha (yoki javob topilguncha) aylanadi. Massivdagi reduce, find/some bilan ma'nosi bir xil. some, every va find erta chiqadi — javob ma'lum bo'lishi bilan to'xtaydi.
const menyu = new Map([
["osh", 35000],
["lag'mon", 28000],
["manti", 30000],
["ko'k choy", 5000],
]);
console.log(menyu.values().reduce((a, b) => a + b, 0)); // 98000
console.log(menyu.keys().some((t) => t === "osh")); // true
console.log(menyu.keys().find((t) => t.startsWith("m"))); // manti
console.log(menyu.keys().drop(1).take(2).toArray());Konsolda:
98000
true
manti
[ "lag'mon", 'manti' ]drop(1).take(2) — "birinchisini o'tkazib, keyingi ikkitasi". Massivdagi slice(1, 3) ning dangasa egizagi — sahifalashda qulay: drop(sahifa * hajm).take(hajm).
4.2 Callback imzosi boshqacha
Callback imzosi darsida massiv metodlari callback'ni (element, index, array) bilan chaqirishini ko'rgan edik. Iterator helper'larda imzo boshqa:
const natija = ["osh", "manti"]
.values()
.map((taom, i, uchinchi) => `${i}: ${taom}, ${uchinchi}`)
.toArray();
console.log(natija);Konsolda:
[ '0: osh, undefined', '1: manti, undefined' ]Ikkinchi argument — hisoblagich (0, 1, 2…): "nechanchi qiymat". Uchinchi argument yo'q: iteratorda "butun massiv" degan narsa yo'q — u faqat navbatdagisini biladi. Massiv kodini iteratorga ko'chirganda (x, i, arr) => arr... ishlatilgan joylarni tekshiring.
4.3 flatMap — faqat iterable qaytaring
const buyurtma = ["osh", "manti"];
const ikkitadan = buyurtma
.values()
.flatMap((t) => [t, t])
.toArray();
console.log(ikkitadan); // [ 'osh', 'osh', 'manti', 'manti' ]flatMap callback'i iterable (massiv, Set, generator) qaytarishi kerak. Massivdagi flatMap (flat, flatMap) oddiy qiymatni ham qabul qiladi, iteratorniki esa — yo'q. Bitta istisno — satr: u iterable bo'lsa ham rad etiladi. Satrni harflarga bo'lib yuborish ko'pincha xato bo'lgani uchun standart uni ataylab taqiqlagan. Xabari «Ko'p uchraydigan xatolar» bo'limida.
Tekshirib ko'ring:
["a", "b", "c"].values().map((x, i) => x + i).toArray()nima qaytaradi?
Javob
[ 'a0', 'b1', 'c2' ]. Ikkinchi argument — hisoblagich, u 0 dan boshlanadi. Bu yerda u massiv indeksiga teng chiqdi, lekin filter dan keyingi map da farq qiladi: hisoblagich map ga yetib kelgan qiymatlarni sanaydi, asl massivdagi o'rinni emas.
5. Cheksiz ketma-ketliklar bilan
Iterator helpers'ning eng kuchli joyi — cheksiz generatorlar. Generator funksiyalar darsidagi navbat chiptalarini eslang:
function* chiptalar() {
let raqam = 1;
while (true) {
yield raqam++;
}
}
const omadli = chiptalar()
.filter((r) => r % 7 === 0)
.map((r) => `Chipta №${r} — bepul choy`)
.take(3)
.toArray();
console.log(omadli);Konsolda:
[
'Chipta №7 — bepul choy',
'Chipta №14 — bepul choy',
'Chipta №21 — bepul choy'
]Aksiya: har yettinchi chipta — bepul choy. Cheksiz ketma-ketlikdan dastlabki uchta omadli raqam olindi. Generator 21 marta so'raldi va to'xtadi. Generator funksiyalar darsida buning uchun o'z birinchiN generatorimizni yozgan edik — endi u tayyor: take.
Diqqat:
takesiz cheksiz zanjirgatoArray(),reduce()yokiforEach()— dastur abadiy ishlaydi.filterham xavfli bo'lishi mumkin:chiptalar().filter((r) => r < 0).take(1)— hech qachon mos qiymat topilmaydi,takeesa birinchisini kutaveradi.somevafindfaqat javob topilganda to'xtaydi.
6. Ichidan: helper'ni generator bilan yozamiz
map va filter darslaridan beri odatimiz bor: metodni ishlatishdan oldin uni o'zimiz yozib ko'ramiz. Generator bilan bu juda qisqa:
function* dangasaFiltr(iterable, shart) {
let hisob = 0;
for (const qiymat of iterable) {
if (shart(qiymat, hisob++)) {
yield qiymat;
}
}
}
function* birinchilar(iterable, n) {
if (n <= 0) return;
let berildi = 0;
for (const qiymat of iterable) {
yield qiymat;
if (++berildi === n) return;
}
}
const juftlar = dangasaFiltr([1, 2, 3, 4, 5, 6], (x) => x % 2 === 0);
console.log([...birinchilar(juftlar, 2)]); // [ 2, 4 ]dangasaFiltr — filter ning dangasa nusxasi, birinchilar — take niki. Ikkalasi ham generator: qiymatni bittadan oladi, bittadan beradi, hech narsa yig'maydi. Tayyor helper'lar ichida xuddi shu mantiq, faqat ular zanjir ko'rinishida yoziladi (x.filter().take()), bizniki esa ichma-ich chaqiruv (birinchilar(dangasaFiltr(...))). Zanjir o'qishga qulayroq — standartga aynan shuning uchun qo'shildi.
++berildi === n — avval oshiradi, keyin solishtiradi. Tekshiruv yield dan keyin: n-qiymat berilgach, generator boshqa so'ramay tugaydi (Generator funksiyalar darsidagi 3-mashq).
7. Iterator.from() — o'z iteratoringizga helper'lar
7.1 Qo'lda yozilgan iteratorda metod yo'q
O'z iterable obyektingizni yasash darsidagi qo'lda yozilgan oraliq ni eslang. Uning iteratori — oddiy obyekt, u Iterator.prototype dan meros olmaydi:
function oraliq(boshi, oxiri) {
return {
[Symbol.iterator]() {
let joriy = boshi;
return {
next() {
return joriy < oxiri
? { value: joriy++, done: false }
: { value: undefined, done: true };
},
};
},
};
}
oraliq(1, 6)[Symbol.iterator]().map((x) => x * 2);Konsolda:
TypeError: oraliq(...)[Symbol.iterator](...).map is not a functionGenerator bilan yozilgan oraliq da bu muammo yo'q — generatorlar Iterator.prototype dan meros oladi.
7.2 Iterator.from o'rab beradi
Iterator.from(x) — iterable'ni yoki next() li obyektni oladi va helper'lari bor haqiqiy iterator qaytaradi:
function oraliq(boshi, oxiri) {
return {
[Symbol.iterator]() {
let joriy = boshi;
return {
next() {
return joriy < oxiri
? { value: joriy++, done: false }
: { value: undefined, done: true };
},
};
},
};
}
const toqlar = Iterator.from(oraliq(1, 10))
.filter((x) => x % 2 === 1)
.toArray();
console.log(toqlar); // [ 1, 3, 5, 7, 9 ]
const narxlar = Iterator.from([35000, 28000]).map((n) => n / 1000);
console.log(narxlar.toArray()); // [ 35, 28 ]Iterator — o'rnatilgan global obyekt: barcha iteratorlarning umumiy "ajdodi". Iterator.from unga o'z iterable'ingizni ulaydi. Massiv yoki Set uchun ham ishlaydi (Iterator.from([..]) ≈ [..].values()), lekin ularning o'zida values() bor — Iterator.from asosan o'z yasagan obyektlaringiz va kutubxonalardan kelgan iteratorlar uchun.
Tekshirib ko'ring: Generatorlar chuqur darsidan keyin
VazifalarRoyxatida*[Symbol.iterator]()generator metodi bor.holat.vazifalar[Symbol.iterator]().filter((v) => !v.bajarildi)ishlaydimi, yokiIterator.fromkerakmi?
Javob
Ishlaydi, Iterator.from shart emas: generator metod qaytargan obyekt — generator, u esa Iterator.prototype dan helper'larni meros oladi. Iterator.from(holat.vazifalar) ham to'g'ri — u royxatning [Symbol.iterator]() ini chaqirib, o'sha generatorni qaytaradi. O'tgan darsdagi qo'lda yozilgan iterator bo'lganida esa Iterator.from kerak bo'lardi.
8. Qayerda ishlaydi: Baseline va Node
Iterator helpers — yangi imkoniyat. Ishlatishdan oldin kodingiz qayerda ishlashini o'ylang: sizning serveringizdami yoki mehmonlarning har xil telefonlaridami.
| Imkoniyat | Standart | Brauzerlar | Node 24 |
|---|---|---|---|
map, filter, take, drop, flatMap, reduce, toArray, some, every, find, forEach, Iterator.from |
ES2025 | Chrome/Edge 122, Firefox 131, Safari 18.4 | bor |
Iterator.concat |
ES2026 | Chrome/Edge 146, Firefox 147, Safari 26.4 | yo'q |
Iterator.zip |
taklif | Chrome 154 da bor, Baseline emas | yo'q |
Baseline ma'lumotiga ko'ra, asosiy helper'lar 2025-yil 31-martdan Baseline (barcha asosiy brauzerlarda), lekin hali "widely available" (keng tarqalgan — eski qurilmalar ham yangilanib ulgurgan) emas. Bu belgi Baseline'dan 30 oy o'tib — 2027-yil oxiriga yaqin beriladi. Ya'ni bugun Safari 18.4 dan eski iPhone'larda ular ishlamaydi. Node'da esa ular 22-versiyadan bor; Node 24 da hammasini sinab ko'rdik.
Iterator.concat(a, b) — bir nechta iterable'ni ketma-ket ulaydi, ES2026 da qo'shildi va 2026-yil martidan Baseline. Lekin Node 24 da hali yo'q:
console.log(typeof Iterator.from); // function
console.log(typeof Iterator.concat); // undefinedNode 24 da uning o'rnini Generatorlar chuqur darsidagi yield* bosadi: function* ula(...lar) { for (const x of lar) yield* x; }. Iterator.zip esa — bir nechta iteratorni "juftlab" aylanish taklifi; xaritamizda u ES2027 ga kutilmoqda. Chrome 154 da u allaqachon bor (o'zimiz tekshirdik), lekin Baseline ma'lumotida unga hali belgi berilmagan.
Amaliy qoida:
- Node.js'dagi kod (server, skriptlar, Node 22+) — iterator helpers'ni bemalol ishlating.
- Ommaviy sayt — Baseline "widely available" bo'lguncha yoki ehtiyot uchun: kichik ro'yxatlarda oddiy massiv metodlari; katta yoki cheksiz ketma-ketlikda — generator va
for...of(ular 2016-yildan beri hamma joyda). Yoki Babel/core-js kabi vositalar bilan polyfill — ularni 16-qismda o'rganamiz.
9. Qachon massiv, qachon iterator helper?
| Vaziyat | Tanlov |
|---|---|
| Kichik ro'yxat, hamma element kerak | massiv metodlari — oddiy va biroz tezroq |
| "Birinchi N ta", "birinchi mos" katta to'plamdan | iterator: values().filter().take() |
Map, Set, generator ustida zanjir |
iterator helper — massivga aylantirmasdan |
| Cheksiz ketma-ketlik | faqat iterator helper (take bilan) |
| Natijani qayta-qayta o'qish kerak | massiv (toArray() bilan bir marta yig'ing) |
Oxirgi qatorga e'tibor bering: iterator zanjiri ham iterator — bir martalik. Uni ikki marta aylansangiz, ikkinchisi bo'sh bo'ladi.
10. Ko'p uchraydigan xatolar
10.1 toArray() ni unutish
console.log(menyu.values().map(...)) — Object [Iterator Helper] {}. Natija emas, tayyor zanjir. Hech bir callback ishlamagan. Tuzatish: yakunlovchi metod chaqiring — toArray(), reduce(), for...of yoki spread.
10.2 Massivda take / drop ni chaqirish
narxlar.take(3) — TypeError: narxlar.take is not a function («Massivdan to'g'ridan-to'g'ri — yo'q» bo'limi). Tuzatish: narxlar.values().take(3) — yoki massivda slice(0, 3).
10.3 Zanjirni ikki marta ishlatish
const ikkilangan = [1, 2, 3].values().map((x) => x * 2);
console.log([...ikkilangan]); // [ 2, 4, 6 ]
console.log([...ikkilangan]); // []Iterator — bir martalik (Iteratsiya protokoli). Xato chiqmaydi, ikkinchi natija shunchaki bo'sh. Tuzatish: natija qayta kerak bo'lsa — bir marta toArray() qilib, massivni saqlang.
10.4 flatMap dan satr qaytarish
const harflar = ["osh"].values().flatMap((t) => t).toArray();Konsolda:
TypeError: Iterator.prototype.flatMap called on non-objectTarjimasi: "Iterator.prototype.flatMap obyekt bo'lmagan qiymatda chaqirildi". Xabar chalg'itadi: muammo flatMap qayerda chaqirilganida emas, callback qaytargan qiymatda — "osh" satri obyekt emas. Iterator flatMap i satrni ataylab rad etadi («flatMap — faqat iterable qaytaring» bo'limi). Tuzatish: harflar kerak bo'lsa — [...t] qaytaring; satrning o'zi kerak bo'lsa — flatMap emas, map.
10.5 Bo'sh iteratorda boshlang'ichsiz reduce
[].values().reduce((a, b) => a + b) — TypeError: Reduce of a done iterator with no initial value ("tugagan iteratorni boshlang'ich qiymatsiz yig'ib bo'lmaydi"). Massivdagi reduce bilan bir xil qoida (reduce). Tuzatish: doim boshlang'ich qiymat bering — reduce((a, b) => a + b, 0).
10.6 take ga noto'g'ri son
take(-1) yoki take() — RangeError: -1 must be positive / RangeError: undefined must be positive ("musbat bo'lishi kerak"). slice manfiy sonni "oxiridan" deb tushunadi, take esa — yo'q: iteratorda "oxiri" noma'lum. Tuzatish: 0 yoki musbat son bering.
11. Mashqlar
1-mashq (oson): Arzon taomlar
«Bahor» menyusi Map da (osh 35 000, lag'mon 28 000, manti 30 000, ko'k choy 5 000). Iterator helpers bilan narxi 30 000 dan oshmaydigan taomlar nomini katta harf bilan massivga yig'ing. [...menyu] ishlatmang — entries() dan boshlang.
Yechim
const menyu = new Map([
["osh", 35000],
["lag'mon", 28000],
["manti", 30000],
["ko'k choy", 5000],
]);
const arzonlar = menyu
.entries()
.filter(([, narx]) => narx <= 30000)
.map(([taom]) => taom.toUpperCase())
.toArray();
console.log(arzonlar); // [ "LAG'MON", 'MANTI', "KO'K CHOY" ]([, narx]) — destructuring'da birinchi elementni (kalitni) o'tkazib yuborish: vergul oldida nom yo'q (Massiv destructuring). Map hech qachon massivga aylanmadi — juftliklar to'g'ridan-to'g'ri filter va map dan o'tdi.
2-mashq (o'rta): Bo'sh bron vaqtlari
Bron yarim soatlik oraliqlarda: 10:00, 10:30, 11:00… Band vaqtlar — new Set(["10:00", "11:00", "11:30"]). Cheksiz function* yarimSoatlar(boshSoat) generatorini yozing ("10:00", "10:30", "11:00"… satrlarini bersin). So'ng iterator helpers bilan birinchi uchta bo'sh vaqtni oling. Soat va daqiqani satrga: `${soat}:${daqiqa === 0 ? "00" : "30"}`.
Yechim
function* yarimSoatlar(boshSoat) {
for (let soat = boshSoat; ; soat++) {
yield `${soat}:00`;
yield `${soat}:30`;
}
}
const band = new Set(["10:00", "11:00", "11:30"]);
const boshVaqtlar = yarimSoatlar(10)
.filter((vaqt) => !band.has(vaqt))
.take(3)
.toArray();
console.log(boshVaqtlar); // [ '10:30', '12:00', '12:30' ]for (let soat = boshSoat; ; soat++) — shartsiz for: o'rta qism bo'sh, sikl cheksiz. Generatorda bu xavfsiz — har yield da pauza. Daqiqa formulasi o'rniga ikki yield yozildi: soat va yarim soat. take(3) uchinchi bo'sh vaqtda zanjirni to'xtatdi — generator atigi olti satr yasadi. Haqiqiy ilovada yuqori chegara ham qo'ying: yarimSoatlar(10).take(24) — 10:00 dan 22:00 gacha bo'lgan 24 ta oraliq. Aks holda hamma vaqt band bo'lsa, filter bo'sh vaqtni abadiy qidiradi («Cheksiz ketma-ketliklar bilan» bo'limidagi ogohlantirish).
3-mashq (qiyin): O'z Iterator.concat ingiz
Node 24 da Iterator.concat yo'q. ula(...iterablelar) funksiyasini yozing: u bir nechta iterable'ni ketma-ket ulab, helper'lari bor iterator qaytarsin. Ya'ni ula(a, b).map(...) ishlashi kerak. Ishora: yield* va generator — generatorlar helper'larni meros oladi.
const issiq = ["osh", "manti"];
const ichimlik = new Set(["ko'k choy"]);
console.log(ula(issiq, ichimlik).map((t) => t.length).toArray());
// [ 3, 5, 9 ]Yechim
function* ula(...iterablelar) {
for (const iterable of iterablelar) {
yield* iterable;
}
}
const issiq = ["osh", "manti"];
const ichimlik = new Set(["ko'k choy"]);
const zanjir = ula(issiq, ichimlik).map((t) => t.length);
console.log(zanjir.toArray()); // [ 3, 5, 9 ]
console.log(ula("ab", [1]).toArray()); // [ 'a', 'b', 1 ]...iterablelar — rest parametr (Spread va rest): istalgan sondagi argumentni massivga yig'adi. Har biri uchun yield* ishni o'sha iterable'ga topshiradi (Generatorlar chuqur). ula generator funksiya bo'lgani uchun qaytgan obyekt Iterator.prototype dan meros oladi — map va toArray o'z-o'zidan bor. Iterator.concat ishlaydigan muhitda ula ni u bilan almashtirish mumkin.
4-mashq: Vazifalar qadami — helper'lar royxat ustida (mashqlar repo)
Generatorlar chuqur darsidan keyin VazifalarRoyxati iteratori — generator, demak unda iterator helpers bor. Bu qadam mashqlar reposida: kurs/mashqlar/10/54-iterator-helpers/royxat.js.
- Royxatning qisqa nusxasini ko'chiring (
#vazifalar,static dan,statistika()—Object.groupBybilan,*[Symbol.iterator]()). - Iterator helpers bilan, royxatni massivga aylantirmasdan hisoblang: faol vazifalar soni, birinchi faol vazifa matni, barcha matnlar "; " bilan.
statistika().qoldibilan solishtiring.- Bitta-ikki gap:
vazifalar.jsdagi metodlarni iterator helpers'ga o'tkazish kerakmi?
Yechim
function guruhNomi(vazifa) {
return vazifa.bajarildi ? "bajarilgan" : "faol";
}
class VazifalarRoyxati {
#vazifalar = [];
static dan(malumotlar) {
const yangi = new VazifalarRoyxati();
yangi.#vazifalar = malumotlar.map((m) => ({ ...m }));
return yangi;
}
statistika() {
const guruhlar = Object.groupBy(this.#vazifalar, guruhNomi);
return {
qoldi: guruhlar.faol?.length ?? 0,
bajarildi: guruhlar.bajarilgan?.length ?? 0,
};
}
*[Symbol.iterator]() {
yield* this.#vazifalar;
}
}
const royxat = VazifalarRoyxati.dan([
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "DOM darsini takrorlash", bajarildi: true },
{ id: 3, matn: "Onamga qo'ng'iroq qilish", bajarildi: false },
]);
const faollar = Iterator.from(royxat)
.filter((v) => !v.bajarildi)
.reduce((soni) => soni + 1, 0);
const birinchiFaol = Iterator.from(royxat).find((v) => !v.bajarildi);
const matnlar = Iterator.from(royxat)
.map((v) => v.matn)
.toArray()
.join("; ");
console.log(faollar, royxat.statistika().qoldi); // 2 2
console.log(birinchiFaol.matn); // Non olish
console.log(matnlar);Konsolda:
2 2
Non olish
Non olish; DOM darsini takrorlash; Onamga qo'ng'iroq qilishIterator.from(royxat) royxatning generatorini oldi. Har hisob uchun yangi Iterator.from chaqirildi — iterator bir martalik. join — massiv metodi, shuning uchun avval toArray(). Iteratorlar uchun join ham tayyorlanmoqda (Chrome 153, Firefox 154 da bor), lekin u hali Baseline emas va Node 24 da yo'q.
Javob: o'tkazmaymiz. vazifalar dagi ro'yxat kichik va hamma element kerak — massiv metodlari bu yerda oddiyroq va biroz tezroq («O'lchaymiz» bo'limidagi grafik). Ilova ommaviy saytda (GitHub Pages) ishlaydi, iterator helpers esa hali "widely available" emas — Safari 18.4 dan eski telefonlarda ilova ishlamay qolardi. Royxatning iterable bo'lgani foydali — kerak bo'lsa helper'lar tayyor. Lekin "yangi" degani "yaxshiroq" degani emas.
Commit (mashqlar repo): 10/54: royxat ustida iterator helpers bilan hisob.
12. Real ishda
- Node.js skriptlari va serverlar. Katta log fayllarni, baza natijalarini qatorma-qator qayta ishlashda
filter().map().take()— oraliq massivsiz, xotirani tejab. Node 22+ da tayyor. - Ma'lumot oqimlari. Sahifalab keladigan API natijalari, fayl qatorlari — generator + helper'lar. Asinxron variantlari (
for await...of, async generator) Asinxron iteratsiya darsida. - Kutubxonalar o'rnini egallash. Ilgari dangasa zanjir uchun Lodash'ning
_.chainyoki iter-tools, IxJS kabi kutubxonalar kerak edi. Endi asosiy qismi tilning o'zida — bog'liqlik kamayadi. - Intervyu. "Iterator helpers nima va massiv metodlaridan farqi?", "Dangasa hisob qachon foydali, qachon zararli?" — 2025-yildan beri yangi, lekin tez-tez beriladigan savollar. Grafikdagi ikki xulosa — tayyor javob.
Xulosa
- Har bir o'rnatilgan iterator (massiv
values(),Map/Set, generator) ES2025 danmap,filter,take,drop,flatMap,reduce,toArray,some,every,find,forEachga ega. - O'zgartiruvchilar yangi iterator qaytaradi va hech narsa hisoblamaydi; yakunlovchilar zanjirni ishga tushiradi.
- Zanjir elementma-element ishlaydi: "birinchi N ta" da yuzlab marta tez, "hammasi" da massivdan biroz sekin.
- Callback imzosi —
(qiymat, hisoblagich), uchinchi argument yo'q;flatMapsatr qaytarishni qabul qilmaydi. Iterator.from()— qo'lda yozilgan iterator yoki iterable'ga helper'lar beradi.- Baseline 2025 (Chrome 122, Firefox 131, Safari 18.4), hali widely available emas; Node 22+ da bor.
Iterator.concat— Node 24 da yo'q.
Keyingi dars: try / catch / finally — xatolarni ushlash: generator darslarida ko'rgan try va catch ni to'liq o'rganamiz.
Manbalar
- MDN: "Iterator", "Iterator.prototype.map()", "Iterator.from()", "Iterator.concat()" — developer.mozilla.org
- TC39 taklifi: "Iterator Helpers" (ES2025) — github.com/tc39/proposal-iterator-helpers
- web-features 3.40 (npm paketi):
iterator-methods— Baseline 2025-03-31;iterator-concat— Baseline 2026-03-24
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!