Mundarija (35)
- Bu darsda
- 1. Nega bu kerak?
- 2. To'rt juftlik
- 3. toSorted — saralangan nusxa
- 3.1 Birinchi misol
- 3.2 toSorted ichidan
- 3.3 Eski tuzoq joyida
- 4. toReversed — teskari nusxa
- 5. toSpliced — o'chirish va qo'shish nusxada
- 5.1 Argumentlar — splice dagidek
- 5.2 Eng muhim farq: nima qaytaradi
- 6. with — bitta elementni almashtirish
- 6.1 Indeks va yangi qiymat
- 6.2 Chegaradan tashqari — xato
- 7. Nusxa sayoz
- 7.1 Obyektlar umumiy qoladi
- 7.2 Obyekt elementni xavfsiz yangilash
- 8. Immutable yangilash va React
- 8.1 Atama
- 8.2 React shunday ishlaydi
- 9. Qayerda ishlaydi
- 10. Mutatsiya qachon joiz?
- 11. Ko'p uchraydigan xatolar
- 11.1 Natijani saqlamaslik
- 11.2 toSpliced natijasini o'chirilganlar deb o'ylash
- 11.3 Nusxani chuqur deb o'ylash
- 11.4 with bilan element qo'shishga urinish
- 12. Mashqlar
- 1-mashq (oson): Yangilari tepada
- 2-mashq (o'rta): Savatda sonni o'zgartirish
- 3-mashq (qiyin): "Bekor qilish" tugmasi
- 4-mashq: Vazifalar qadami — nusxa metodlariga o'tish
- 13. Real ishda
- Xulosa
- Manbalar
JavaScript toSorted, toReversed, toSpliced va with: massivni nusxa bilan o'zgartirish
Qisqacha: ES2023 da massivga to'rtta yangi metod qo'shildi. Ular
sort,reverse,splicevamassiv[i] = xning ishini qiladi, lekin asl massivga tegmaydi — o'zgartirilgan yangi nusxa qaytaradi:const arzondan = narxlar.toSorted((a, b) => a - b). Nusxa sayoz: ichidagi obyektlar umumiy qoladi.
Bu darsda
toSorted,toReversed,toSplicedvawithbilan asl massivga tegmay, yangi massiv yasay olasiz.- Har yangi metodning "eski" juftini va ularning farqini — ayniqsa
splicevatoSplicedqaytaradigan qiymatni — aytib bera olasiz. - Immutable yangilash nima ekanini va u nega React kabi vositalarda majburiy ekanini tushuntira olasiz.
- Nusxa sayoz ekanini va obyekt elementni qanday xavfsiz yangilashni bilasiz.
vazifalardasortvaspliceni nusxa metodlariga almashtirasiz.
Oldin bilishingiz kerak: sort va taqqoslash funksiyasi, Element qo'shish va olib tashlash, Kesish, birlashtirish va matnga aylantirish, Havola semantikasi, Sayoz va chuqur nusxalash.
1. Nega bu kerak?
sort darsida Otabek menyuni "arzondan qimmatga" ko'rmoqchi bo'ldi va asl menyuni buzib qo'ydi. Tuzatish — avval nusxa olish edi:
const arzondan = [...menyu].sort((a, b) => a.narx - b.narx);Bu ishlaydi. Lekin uchta kamchiligi bor:
- Unutish oson.
[...]ni yozmasangiz, kod baribir ishlaydi — faqat aslini jimgina buzadi. - Niyat yashiringan.
[...menyu]ni o'qigan odam "nega bu yerda nusxa?" deb o'ylab qoladi. Nusxa saralash uchunmi yoki boshqa sabab bormi? - Har metodga o'z usuli.
reverseuchun ham[...],spliceuchun esa boshqacha:sliceva spread bilan bo'laklardan yig'ish kerak.
2023-yilda JavaScript standarti (ES2023) bu muammoni hal qildi. Mutatsiya qiladigan to'rt amalning har biriga nusxa bilan ishlaydigan juft qo'shildi. Ularning ikkitasini — toSpliced va with ni — Element qo'shish va olib tashlash darsida ko'rib o'tgan edik, toReversed ni esa Kesish va birlashtirish darsida. Bugun to'rttalasini to'liq o'rganamiz.
Hayotdan o'xshatish: rasmiy hujjat va uning nusxasi. Tuman hokimiyatiga ariza berasiz. Pasportning aslini emas, nusxasini topshirasiz — kserokopiyada xodim belgi qo'yadi, muhr bosadi. Pasportingizga esa qalam ham tegmaydi. Yangi metodlar shunday ishlaydi: o'zgarishlar nusxaga yoziladi, asl massiv qo'lingizda butun qoladi.
2. To'rt juftlik
| Mutatsiya qiladi | Nusxa qaytaradi | Nima qiladi |
|---|---|---|
sort(taqqosla) |
toSorted(taqqosla) |
saralaydi |
reverse() |
toReversed() |
teskari aylantiradi |
splice(boshi, soni, ...yangi) |
toSpliced(boshi, soni, ...yangi) |
o'chiradi, qo'shadi, almashtiradi |
massiv[i] = qiymat |
with(i, qiymat) |
bitta elementni almashtiradi |
Nomlash qoidasi oddiy: eski nom oldiga to qo'shilgan — inglizcha "toSorted" taxminan "saralanganga aylantir" degani. Argumentlar ham xuddi o'sha. sort ni bilsangiz — toSorted ni ham bilasiz. Faqat with istisno: tayinlash = metod emas, shuning uchun unga alohida nom berilgan — "shu indeksda shu qiymat bilan".
Ikki guruhning farqini sxemada ko'ring. «menyu.sort(...)» qutisida ikki nom bitta massivga qaraydi, «menyu.toSorted(...)» qutisida — ikki xil massivga:
flowchart LR
subgraph S["menyu.sort(...)"]
A1["menyu"] --> M1["bitta massiv: saralangan"]
A2["arzondan"] --> M1
end
subgraph T["menyu.toSorted(...)"]
B1["menyu"] --> N1["asl massiv: o'zgarmagan"]
B2["arzondan"] --> N2["yangi massiv: saralangan"]
end3. toSorted — saralangan nusxa
3.1 Birinchi misol
const narxlar = [35000, 28000, 5000];
const arzondan = narxlar.toSorted((a, b) => a - b);
console.log(arzondan); // [ 5000, 28000, 35000 ]
console.log(narxlar); // [ 35000, 28000, 5000 ]
console.log(arzondan === narxlar); // falseSaralangan narxlar — yangi massivda. narxlar — avvalgi tartibida. === ham buni tasdiqlaydi: ikki xil massiv.
3.2 toSorted ichidan
Oldingi darslardagidek, metodning soddalashtirilgan nusxasini yozamiz. U juda qisqa — chunki ichida eski sort ishlaydi:
function nusxadaSaralash(massiv, taqqosla) {
const nusxa = [...massiv];
nusxa.sort(taqqosla);
return nusxa;
}
const narxlar = [35000, 28000, 5000];
console.log(nusxadaSaralash(narxlar, (a, b) => a - b));
console.log(narxlar);Konsolda:
[ 5000, 28000, 35000 ]
[ 35000, 28000, 5000 ]Mohiyatan toSorted — [...massiv].sort() ning nomli, standart shakli. Yangi g'oya yo'q, lekin kod niyatni o'zi aytadi va nusxani unutish imkoni qolmaydi.
3.3 Eski tuzoq joyida
toSorted faqat mutatsiya masalasini hal qiladi. Taqqoslash funksiyasisiz u ham sonlarni satr sifatida saralaydi:
const narxlar = [35000, 28000, 5000];
console.log(narxlar.toSorted()); // [ 28000, 35000, 5000 ]O'tgan darsdagi barcha qoidalar kuchida: sonlar uchun (a, b) => a - b, matnlar uchun localeCompare. Saralash ham barqaror.
Tekshirib ko'ring:
const a = [3, 1, 2]; const b = a.toSorted(); b.push(4);—aqanday ko'rinishda?
Javob
[ 3, 1, 2 ]. toSorted yangi massiv qaytardi, b.push(4) esa shu yangisini o'zgartirdi. a bilan b endi hech qanday bog'liq emas — ichida faqat sonlar, sonlar esa nusxalanadi.
4. toReversed — teskari nusxa
Kesish va birlashtirish darsida reverse navbatdagi odamlar tartibini buzib qo'ygan edi. toReversed buni xavfsiz qiladi:
const navbat = ["Ali", "Malika", "Jasur"];
const oxiridan = navbat.toReversed();
console.log(oxiridan); // [ 'Jasur', 'Malika', 'Ali' ]
console.log(navbat); // [ 'Ali', 'Malika', 'Jasur' ]Real ishda ko'p kerak bo'ladigan holat: ma'lumot eskidan yangiga qarab saqlanadi, ekranga esa yangilari tepada chiqishi kerak. Telegram'dagi kanal postlari, bank ilovasidagi o'tkazmalar tarixi — hammasi shunday. Ma'lumotning o'zini aylantirish shart emas: ko'rsatishda toReversed() kifoya.
Nusxa metodlari ham massiv qaytaradi, demak ularni bir-biriga yoki boshqa metodlarga ulash mumkin. "Eng qimmat ikki taom" — saralangan nusxadan boshini kesib olish:
const narxlar = [28000, 35000, 5000, 30000];
const engQimmat = narxlar.toSorted((a, b) => b - a).slice(0, 2);
console.log(engQimmat); // [ 35000, 30000 ]
console.log(narxlar); // [ 28000, 35000, 5000, 30000 ]toSorted yangi massiv berdi, slice undan yana bittasini kesdi. Asl narxlar butun. Bunday zanjirlarni Metod zanjiri darsida batafsil ko'ramiz.
Tekshirib ko'ring:
const a = [1, 2, 3]; const b = a.toReversed().toReversed();—bvaateng ko'rinadimi?a === bnima beradi?
Javob
Ko'rinishi bir xil — [ 1, 2, 3 ], ikki marta aylantirilgan tartib asliga qaytdi. Lekin a === b — false. Har toReversed yangi massiv yasadi, b — ikkinchi nusxa. === massivning ichini emas, havolasini solishtiradi (Havola semantikasi).
5. toSpliced — o'chirish va qo'shish nusxada
5.1 Argumentlar — splice dagidek
toSpliced(boshi, soni, ...yangilar): boshi indeksidan soni ta elementni olib tashlaydi va o'rniga yangilar ni qo'yadi. Uchala ishi ham bor:
const savat = ["non", "sut", "tuxum"];
console.log(savat.toSpliced(1, 1)); // [ 'non', 'tuxum' ]
console.log(savat.toSpliced(1, 0, "choy"));
// [ 'non', 'choy', 'sut', 'tuxum' ]
console.log(savat.toSpliced(-1, 1, "qatiq"));
// [ 'non', 'sut', 'qatiq' ]
console.log(savat); // [ 'non', 'sut', 'tuxum' ]Birinchisi — o'chirish, ikkinchisi — qo'shish (soni — 0), uchinchisi — almashtirish. Manfiy indeks oxiridan sanaladi: -1 — oxirgi element. Uchala natija ham yangi massiv, savat esa har safar o'z holida.
Uchta argumentni bitta jumla bilan o'qish odat qiling: "qayerdan boshlab, nechtasini olib tashla va o'rniga nimalarni qo'y". toSpliced(1, 0, "choy") — "1-o'rindan boshlab, hech narsani olib tashlama, choy ni qo'y". Ikkinchi argument — indeks emas, soni: Element qo'shish va olib tashlash darsidagi splice tuzog'i bu yerda ham bor.
O'zingiz to'ldiring. ["a", "b", "c", "d"].toSpliced(1, 2) natijasida nechta element qoladi — [:2]. ["a", "b"].toSpliced(1, 0, "x", "y") natijasining uzunligi — [:4].
5.2 Eng muhim farq: nima qaytaradi
splice va toSpliced argumentlari bir xil, lekin qaytaradigan narsasi butunlay boshqa:
const birinchi = ["non", "sut", "tuxum"];
const ikkinchi = ["non", "sut", "tuxum"];
console.log(birinchi.splice(1, 1)); // [ 'sut' ]
console.log(ikkinchi.toSpliced(1, 1)); // [ 'non', 'tuxum' ]splice |
toSpliced |
|
|---|---|---|
| Asl massiv | o'zgaradi | o'zgarmaydi |
| Qaytaradi | o'chirilgan elementlar | yangi massiv (qolganlar bilan) |
splice ning natijasi — "chiqarib olingan narsalar", chunki yangi massiv uning o'zida, asl o'zgaruvchida. toSpliced da esa asl o'zgarmaydi, demak yangi holatni faqat natija sifatida berish mumkin. O'chirilgan elementlar kerak bo'lsa, ularni slice(boshi, boshi + soni) bilan alohida olasiz.
Tekshirib ko'ring:
const s = ["a", "b", "c"]; const n = s.toSpliced(0, 2);—nvasnima?
Javob
n — [ 'c' ]: 0-indeksdan ikkita element (a, b) olib tashlangan nusxa. s — [ 'a', 'b', 'c' ], o'zgarmagan. splice(0, 2) bo'lganida natija aksincha — [ 'a', 'b' ] (o'chirilganlar) bo'lardi va s ning o'zi [ 'c' ] ga aylanardi.
6. with — bitta elementni almashtirish
6.1 Indeks va yangi qiymat
const menyu = ["osh", "lag'mon", "manti"];
console.log(menyu.with(1, "chuchvara"));
// [ 'osh', 'chuchvara', 'manti' ]
console.log(menyu.with(-1, "somsa")); // [ 'osh', "lag'mon", 'somsa' ]
console.log(menyu); // [ 'osh', "lag'mon", 'manti' ]with(1, "chuchvara") — "1-indeksi chuchvara bo'lgan nusxa". Manfiy indeks bu yerda ham oxiridan sanaladi — menyu[-1] esa bunday ishlamaydi (Massiv: yaratish va elementga murojaat).
6.2 Chegaradan tashqari — xato
Tayinlash = massiv chegarasidan tashqariga ham yozadi va "teshiklar" qoldiradi:
const savat = ["non", "sut", "tuxum"];
savat[5] = "choy";
console.log(savat);
// [ 'non', 'sut', 'tuxum', <2 empty items>, 'choy' ]<2 empty items> — 3- va 4-o'rinlar bo'sh qoldi. Bunday teshikli massivlar metodlarda kutilmagan xulq ko'rsatadi (Massivga o'xshash obyektlar va teshikli massivlar darsida). with esa bunga yo'l qo'ymaydi:
const savat = ["non", "sut", "tuxum"];
console.log(savat.with(5, "choy"));RangeError: Invalid index : 5Tarjimasi: "diapazon xatosi: noto'g'ri indeks: 5". RangeError — qiymat ruxsat etilgan oraliqdan tashqarida bo'lganda chiqadigan xato turi (Stack trace va xato turlari). Uch elementli massivda ruxsat etilgan indekslar — -3 dan 2 gacha. with faqat bor elementni almashtiradi, yangisini qo'shmaydi. Yangi element kerak bo'lsa — spread: [...savat, "choy"].
Tekshirib ko'ring:
["a", "b"].with(-2, "x")nima qaytaradi?["a", "b"].with(2, "x")-chi?
Javob
Birinchisi — [ 'x', 'b' ]: -2 — oxiridan ikkinchi, ya'ni 0-indeks. Ikkinchisi — RangeError: ikki elementli massivda 2-indeks yo'q.
7. Nusxa sayoz
7.1 Obyektlar umumiy qoladi
Yangi metodlar yangi massiv yasaydi, lekin elementlarni nusxalamaydi. Elementlar obyekt bo'lsa — ikki massivda o'sha obyektlar turadi (Sayoz va chuqur nusxalash):
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Manti", narx: 30000 },
];
const arzondan = menyu.toSorted((a, b) => a.narx - b.narx);
arzondan[0].narx = 0;
console.log(menyu[1].narx); // 0
console.log(arzondan[0] === menyu[1]); // trueMassivlar ikkita, mantining obyekti — bitta. Nusxa orqali uning narxini o'zgartirsak, asl menyudagi manti ham tekinga aylandi. toSorted "massivning tartibini" himoya qiladi, ichidagi obyektlarni emas.
7.2 Obyekt elementni xavfsiz yangilash
Manti narxini 32 000 ga ko'tarish kerak, aslini buzmasdan. Yechim — yangi obyekt yasab, uni with bilan joylash:
const menyu = [
{ nom: "Osh", narx: 35000 },
{ nom: "Manti", narx: 30000 },
];
const yangiMenyu = menyu.with(1, { ...menyu[1], narx: 32000 });
console.log(yangiMenyu[1]); // { nom: 'Manti', narx: 32000 }
console.log(menyu[1]); // { nom: 'Manti', narx: 30000 }
console.log(yangiMenyu[0] === menyu[0]); // true{ ...menyu[1], narx: 32000 } — mantining hamma maydonlari, faqat narx yangi (Spread). Asl obyektga tegilmadi. O'zgarmagan osh esa ikki massivda umumiy — bu xato emas, tejamkorlik: o'zgarmagan narsani nusxalash shart emas.
map darsidagi map((x) => x.id === id ? { ...x, ... } : x) ham xuddi shu ishni qiladi. Farqi: map elementni shart bo'yicha topadi, with — indeks bo'yicha. Ichma-ich ma'lumotni shunday yangilashni Ichma-ich ma'lumotni immutable yangilash darsida chuqurroq ko'ramiz.
8. Immutable yangilash va React
8.1 Atama
Immutable yangilash — eski qiymatga tegmasdan, o'zgarishlari bor yangi qiymat yasash. Bu atamani map darsida, bitta vazifani yangilashda uchratgan edik. Inglizcha "mutable" — "o'zgaruvchan" (mutatsiya ham shu so'zdan), "immutable" — "o'zgarmas". Bugungi to'rt metod — massiv uchun immutable yangilash vositalari.
Nima uchun bunga shunchalik e'tibor berishadi? Chunki yangi massiv — "nimadir o'zgardi" degan aniq signal. Uni bitta === bilan tekshirish mumkin:
function ozgardimi(eski, yangi) {
return eski !== yangi;
}
const navbat = ["Ali", "Malika"];
const birinchi = navbat.toReversed();
console.log(ozgardimi(navbat, birinchi)); // true
const ikkinchi = navbat.reverse();
console.log(ozgardimi(navbat, ikkinchi)); // falsetoReversed dan keyin ozgardimi — true: yangi massiv, demak o'zgarish bor. reverse dan keyin esa false. Tartib aslida o'zgardi, lekin reverse o'sha massivni qaytardi — tashqaridan qaraganda "hech narsa bo'lmagan".
8.2 React shunday ishlaydi
Bu shunchaki tajriba emas. React — sayt interfeysini yasash kutubxonasi, uni 17-qismda o'rganamiz, hozir bilish shart emas. U ekranni qachon qayta chizishni aynan shunday hal qiladi: holatning eski va yangi qiymatini havola bo'yicha solishtiradi. Siz vazifalar.sort(...) qilsangiz, React "massiv o'sha-o'sha" deb ko'radi va ekranni yangilamaydi. vazifalar.toSorted(...) — yangi massiv, ekran yangilanadi.
Shuning uchun React kodida sort, reverse, splice, push va massiv[i] = ... holat uchun deyarli uchramaydi. O'rnida — bugungi to'rt metod, map, filter va spread. Siz 09-qismdagi vazifalar ni 17-qismda React'da qayta yozganingizda, bu odat tayyor bo'ladi.
Tekshirib ko'ring: Holatda
const savat = ["non", "sut"]bor. Quyidagilardan qaysi birisavatga havola bo'yicha "o'zgardi" signalini beradigan yangi massiv yasaydi:savat.push("choy"),[...savat, "choy"],savat.toSpliced(2, 0, "choy")?
Javob
Ikkinchisi va uchinchisi. Ikkalasi ham [ 'non', 'sut', 'choy' ] dan iborat yangi massiv qaytaradi, savat esa o'zgarmaydi. push asl massivni o'zgartiradi va yangi uzunlikni — 3 sonini — qaytaradi. Massiv havola bo'yicha o'sha-o'sha qoladi.
9. Qayerda ishlaydi
Metodlar ES2023 standartida. Brauzerlarda: Chrome va Edge 110, Firefox 115, Safari 16 dan. Node'da — 20-versiyadan. Baseline ma'lumotiga ko'ra, 2026-yil 4-yanvardan ular Baseline widely available ("keng qo'llaniladi"): oxirgi 2,5 yil ichidagi barcha asosiy brauzerlarda bor.
Node versiyangizni terminalda node --version bilan tekshiring: kursda Node 24 ishlatamiz, unda to'rttala metod bor. Brauzer versiyasini esa Chrome'da manzil qatoriga chrome://version yozib ko'rasiz.
Eski brauzerda (masalan, yangilanmagan telefonda) menyu.toSorted is not a function xatosi chiqadi. Bunday foydalanuvchilar ko'p bo'lsa, [...menyu].sort(...) — har joyda ishlaydigan zaxira yo'l. Natijasi bir xil.
TypedArray lar (Typed arrays) ham toSorted, toReversed va with ga ega, lekin toSpliced ga emas.
10. Mutatsiya qachon joiz?
Bugungi darsdan "sort va splice — yomon" degan xulosa chiqmasin. Mutatsiyaning o'zi xato emas. Xavf faqat bitta joyda: massivni boshqa kod ham ishlatayotgan bo'lsa — holat, funksiya argumenti, boshqa modul ma'lumoti.
Funksiya ichida o'zi yaratgan massivni o'zgartirish esa butunlay xavfsiz:
function chekQatorlari(savat) {
const qatorlar = savat.map((m) => `${m.nom}: ${m.narx}`);
qatorlar.sort((a, b) => a.localeCompare(b));
qatorlar.push(`Jami: ${savat.length} ta`);
return qatorlar;
}
const savat = [
{ nom: "Osh", narx: 35000 },
{ nom: "Ko'k choy", narx: 5000 },
];
console.log(chekQatorlari(savat));
console.log(savat[0].nom); // OshKonsolda:
[ "Ko'k choy: 5000", 'Osh: 35000', 'Jami: 2 ta' ]
Oshqatorlar — map yasagan yangi massiv. Uni funksiyadan tashqarida hech kim ko'rmagan, shuning uchun sort va push hech kimga zarar qilmaydi. Bu reduce darsidagi akkumulyator qoidasining o'zi: "o'zing yaratgan narsani o'zgartirish mumkin". savat esa butun.
Yana bir sabab — tezlik. Nusxa olish har safar butun massivni ko'chirish demak. Million elementli massivni bir necha marta toSorted qilish million elementni bir necha marta nusxalaydi. Odatdagi ro'yxatlarda (yuzlab, minglab element) bu farq sezilmaydi. Juda katta ma'lumotda esa "bir marta nusxa, keyin joyida ishlash" yaxshiroq bo'lishi mumkin. Bunday qarorlarni taxmin bilan emas, o'lchab qabul qilish kerak — Metod zanjiri darsida o'lchaymiz.
Qoida bitta savolga keladi: "bu massivni mendan boshqa kim ko'radi?" Hech kim — sort, push erkin. Kimdir ko'rsa — nusxa metodlari.
11. Ko'p uchraydigan xatolar
11.1 Natijani saqlamaslik
const narxlar = [35000, 5000];
narxlar.toSorted((a, b) => a - b);
console.log(narxlar); // [ 35000, 5000 ]sort odatida yozilgan: natijaga e'tibor berilmagan. toSorted aslini o'zgartirmaydi, yangi massiv esa hech qayerga saqlanmadi — tashlab yuborildi. Tuzatish: const arzondan = narxlar.toSorted(...) yoki holat bo'lsa — holat.narxlar = holat.narxlar.toSorted(...).
11.2 toSpliced natijasini o'chirilganlar deb o'ylash
«Eng muhim farq: nima qaytaradi» bo'limidagi jadval. const ochirilgan = savat.toSpliced(1, 1) — ochirilgan da "sut" emas, sutsiz savat bo'ladi. Tuzatish: o'chirilganlar kerak bo'lsa — slice(1, 2).
11.3 Nusxani chuqur deb o'ylash
«Nusxa sayoz» bo'limidagi manti. toSorted dan keyin arzondan[0].narx = 0 asl menyuni ham o'zgartiradi. Xato xabari yo'q. Tuzatish: obyektni o'zgartirish o'rniga yangi obyekt yasang — with(i, { ...eski, narx: yangi }).
11.4 with bilan element qo'shishga urinish
savat.with(savat.length, "choy") — RangeError: Invalid index : 3. with faqat bor indeksni almashtiradi. Tuzatish: oxiriga qo'shish — [...savat, "choy"], o'rtaga — toSpliced(i, 0, "choy").
12. Mashqlar
1-mashq (oson): Yangilari tepada
Otabekning bugungi buyurtma raqamlari kelish tartibida saqlangan. Ekranga yangilaridan boshlab chiqaring, buyurtmalar esa o'zgarmasin. Ikkalasini ham konsolga chiqarib tekshiring.
const buyurtmalar = [101, 102, 103, 104];Yechim
const buyurtmalar = [101, 102, 103, 104];
const ekranga = buyurtmalar.toReversed();
console.log(ekranga); // [ 104, 103, 102, 101 ]
console.log(buyurtmalar); // [ 101, 102, 103, 104 ]toReversed argument olmaydi. Asl ro'yxat kelish tartibida qoldi — keyingi buyurtma push bilan oxiriga qo'shilsa, tartib buzilmaydi.
2-mashq (o'rta): Savatda sonni o'zgartirish
Click orqali to'lanadigan savatda mijoz ko'k choy sonini 2 dan 3 ga oshirdi va manti'ni olib tashladi. Ikkala o'zgarishni ham asl savat ga tegmasdan bajaring: avval with (choy), keyin natijaga toSpliced (manti). Oxirida yangi savat summasini reduce bilan hisoblang.
const savat = [
{ nom: "Osh", narx: 35000, soni: 1 },
{ nom: "Ko'k choy", narx: 5000, soni: 2 },
{ nom: "Manti", narx: 30000, soni: 1 },
];Yechim
const savat = [
{ nom: "Osh", narx: 35000, soni: 1 },
{ nom: "Ko'k choy", narx: 5000, soni: 2 },
{ nom: "Manti", narx: 30000, soni: 1 },
];
const yangi = savat
.with(1, { ...savat[1], soni: 3 })
.toSpliced(2, 1);
const summa = (royxat) =>
royxat.reduce((jami, m) => jami + m.narx * m.soni, 0);
console.log(yangi.map((m) => `${m.nom} x${m.soni}`));
console.log(summa(yangi), summa(savat));Konsolda:
[ 'Osh x1', "Ko'k choy x3" ]
50000 75000with yangi massiv qaytardi, toSpliced shu yangisiga qo'llandi — zanjir. Asl savat summasi o'zgarmadi (75 000), chunki choyning yangi obyekti yasaldi: { ...savat[1], soni: 3 }. savat[1].soni = 3 deb yozilganida asl savat ham o'zgarardi.
3-mashq (qiyin): "Bekor qilish" tugmasi
Immutable yangilashning eng chiroyli foydasi — tarixni saqlash. Har o'zgarish yangi massiv yasasa, eskilari buzilmasdan qoladi. Ularni bitta tarix massivida saqlab, "bekor qilish"ni yozing:
tarix— savat holatlari ro'yxati, boshida bitta bo'sh savat:[[]]. Joriy savat — oxirgi element:tarix.at(-1).ozgartir(yangiSavat)— yangi holatnitarixoxiriga qo'shadi.bekorQil()— oxirgi holatni olib tashlaydi (agar bittadan ko'p bo'lsa).- Uch o'zgarish qiling ("non" qo'shish, "sut" qo'shish, "non" ni "somsa" ga almashtirish) va ikki marta bekor qiling. Har qadamda joriy savatni chiqaring.
at(-1) — massivning oxirgi elementi (Massiv: yaratish va elementga murojaat). Savatni o'zgartirishda faqat yangi massiv qaytaradigan usullarni ishlating.
Yechim
const tarix = [[]];
const joriy = () => tarix.at(-1);
function ozgartir(yangiSavat) {
tarix.push(yangiSavat);
console.log("o'zgardi:", joriy());
}
function bekorQil() {
if (tarix.length > 1) {
tarix.pop();
}
console.log("bekor:", joriy());
}
ozgartir([...joriy(), "non"]);
ozgartir([...joriy(), "sut"]);
ozgartir(joriy().with(0, "somsa"));
bekorQil();
bekorQil();Konsolda:
o'zgardi: [ 'non' ]
o'zgardi: [ 'non', 'sut' ]
o'zgardi: [ 'somsa', 'sut' ]
bekor: [ 'non', 'sut' ]
bekor: [ 'non' ]Bekor qilish shunchaki pop — chunki eski holatlar buzilmagan. Agar ozgartir da joriy()[0] = "somsa" yozganimizda, "somsa" ikkinchi holatni ham o'zgartirardi. Ular bitta massiv bo'lardi va bekor qilish "non" ni qaytara olmasdi. Massiv tarix ning o'zi push/pop bilan o'zgaradi — bu normal: u tarixni saqlovchi "ombor", holatlarning o'zi esa o'zgarmas. Matn muharrirlaridagi Ctrl+Z ham, Redux kabi holat kutubxonalaridagi "vaqt bo'ylab sayohat" ham shu g'oyaga tayanadi.
4-mashq: Vazifalar qadami — nusxa metodlariga o'tish
Yangi branch: git switch -c refactor/nusxa-metodlar. Xulq o'zgarmaydi — bu refaktoring. Ikki joyni almashtiring:
korinadiganlardagi.sort(faollarOldin)nitoSortedga (sortdarsidagi qadam). U hozir ham xavfsiz —filteryangi massiv berdi. Lekin ertaga kimdirfilterni olib tashlasa,sortjimginaholatni buza boshlaydi.vazifaniOchirdagisplicenitoSplicedga. 09-qismdagi kod:
function vazifaniOchir(id) {
const orin = holat.vazifalar.findIndex((v) => v.id === id);
holat.vazifalar.splice(orin, 1);
render();
}Yechim
function korinadiganlar() {
return holat.vazifalar
.filter((vazifa) => mosmi(vazifa, holat.filtr))
.toSorted(faollarOldin);
}function vazifaniOchir(id) {
const orin = holat.vazifalar.findIndex((v) => v.id === id);
holat.vazifalar = holat.vazifalar.toSpliced(orin, 1);
render();
}Birinchisida toSorted niyatni aytadi: "ko'rsatish uchun saralangan nusxa". Ikkinchisida holat.vazifalar endi o'zgartirilmaydi — unga yangi massiv tayinlanadi. holat — const, lekin bu xato emas: const o'zgaruvchining o'zini qayta tayinlashni taqiqlaydi, uning xususiyatini emas (let va const).
O'chirishni filter bilan ham yozsa bo'lardi: holat.vazifalar.filter((v) => v.id !== id). U findIndex siz, qisqaroq. toSpliced indeks allaqachon ma'lum bo'lganda qulay. Ikkalasi ham to'g'ri — bu darsda toSpliced ni tanladik.
korinadiganlar endi holat ga tegmasligini Node'da tekshiring — har filtrda ko'rinadigan tartib va chaqiruvdan keyingi holat tartibi:
const holat = {
vazifalar: [
{ id: 1, bajarildi: false },
{ id: 2, bajarildi: true },
{ id: 3, bajarildi: false },
],
filtr: "hammasi",
};
function mosmi(vazifa, filtr) {
if (filtr === "faol") {
return !vazifa.bajarildi;
}
if (filtr === "bajarilgan") {
return vazifa.bajarildi;
}
return true;
}
function faollarOldin(a, b) {
return Number(a.bajarildi) - Number(b.bajarildi);
}
function korinadiganlar() {
return holat.vazifalar
.filter((vazifa) => mosmi(vazifa, holat.filtr))
.toSorted(faollarOldin);
}
const idlar = (royxat) => royxat.map((v) => v.id).join(",");
for (const filtr of ["hammasi", "faol", "bajarilgan"]) {
holat.filtr = filtr;
console.log(filtr, idlar(korinadiganlar()), idlar(holat.vazifalar));
}Konsolda:
hammasi 1,3,2 1,2,3
faol 1,3 1,2,3
bajarilgan 2 1,2,3Ikkinchi ustun — ekrandagi tartib (faollar tepada), uchinchisi — holat (doim 1,2,3).
Brauzerda — o'tgan darsdagi tekshiruv ro'yxati, natijalar aynan o'shanday bo'lishi kerak:
- Ochilganda: "Non olish", "Onamga qo'ng'iroq qilish", "DOM darsini takrorlash".
- Vazifani belgilang va qaytaring — u pastga tushadi va o'z joyiga qaytadi.
- O'chiring: fokus qo'shni vazifaning «O'chirish» tugmasiga o'tadi, oxirgisini o'chirsangiz — sarlavhaga. "Hozircha vazifa yo'q…" — avvalgidek.
Commit va main ga qo'shish:
git add assets/js/vazifalar.js
git commit -m "Ro'yxat: toSorted va toSpliced bilan holatga tegmaslik"
git switch main
git merge refactor/nusxa-metodlar
git branch -d refactor/nusxa-metodlar
git push13. Real ishda
- React va Redux. Holatni yangilashning standart usuli — nusxa:
setVazifalar(vazifalar.toSorted(...)). React hujjatlari holatdagi massiv uchunsort,reverse,splicekabi mutatsiya qiluvchi metodlardan qochishni va yangi massiv qaytaradiganlarini ishlatishni o'rgatadi (17-qism). - Ro'yxatni ko'rsatish. "Yangilari tepada", "arzondan qimmatga" — ma'lumotning o'zini emas, ko'rinishini o'zgartirish.
toReversed/toSortedrender ichida xavfsiz. - Bekor qilish va tarix. Matn muharriri, rasm muharriri, forma qoralamalari — 3-mashqdagi g'oya: har holat alohida massiv.
- Kod ko'rib chiqish. Funksiya argument sifatida olgan massivni
sortyokispliceqilsa, tajribali dasturchi buni darhol belgilaydi. "To-" metodlar bu savolni yo'qotadi. - Intervyu. "
sortvatoSortedfarqi?", "splicevatoSplicednima qaytaradi?", "toSortedchuqur nusxa qiladimi?" — javoblar: mutatsiya; o'chirilganlar va yangi massiv; yo'q, sayoz.
Xulosa
toSorted,toReversed,toSpliced,with—sort,reverse,splicevamassiv[i] = xning nusxa bilan ishlaydigan juftlari (ES2023).- Argumentlar eski juftnikidek; asl massiv o'zgarmaydi, natija — yangi massiv. Uni saqlashni unutmang.
spliceo'chirilganlarni qaytaradi,toSpliced— yangi massivni.withchegaradan tashqaridaRangeErrorberadi.toSortedham taqqoslash funksiyasisiz satr tartibida saralaydi.- Nusxa sayoz: obyektni o'zgartirmang, yangisini yasang —
with(i, { ...eski, maydon: yangi }). - Yangi massiv — "o'zgardi" signali (
eski !== yangi). React shu signalga qarab ekranni yangilaydi.
Keyingi dars: flat, flatMap, fill va Array.from — ichma-ich massivlarni tekislash, massivni to'ldirish va istalgan ro'yxatdan massiv yasash.
Manbalar
- MDN: "Array.prototype.toSorted()", "toReversed()", "toSpliced()", "with()" — developer.mozilla.org
- TC39: "Change Array by Copy" taklifi (ES2023) — github.com/tc39/proposal-change-array-by-copy
- web-features: "Array by copy" — Baseline widely available, 2026-01-04
- React hujjatlari: "Updating Arrays in State" — react.dev
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!