2.15-bob: Functional programming asoslari — immutability, pure functions, HOF
2-QISM — JavaScript (0 dan chuqurgacha) · 15-mavzu
1. Kirish va motivatsiya
2.3 (HOF, pure function), 2.7 (map/filter/reduce) va 2.8 (immutability) da funksional g'oyalarni alohida sezdik. Endi ularni bir butun paradigma sifatida — Functional Programming (FP) — o'rganamiz.
FP — dasturlashning bir uslubi (paradigma): kodni toza funksiyalar orqali, ma'lumotni o'zgartirmasdan (immutable), funksiyalarni birlashtirib yozish. Bu — OOP 2.10-bob ga muqobil/qo'shimcha yondashuv.
O'xshatish: OOP — "narsalar" (obyektlar) va ularning xulqi atrofida (mashina, foydalanuvchi). FP — "ma'lumot oqimi va o'zgartirishlar" atrofida: ma'lumot konveyerda 2.7-bob bosqichma-bosqich, har funksiya uni o'zgartirmasdan yangisini yasab o'tkazadi. FP — matematik funksiyaga o'xshash: bir xil kirish bir xil chiqish, hech qanday "yon ta'sir".
Nega FP muhim? React (11), Redux (12.2) — chuqur funksional. Toza, bashoratli, test qilishga oson, parallel-do'st kod. FP'ni bilish — zamonaviy frontend'ni chuqur tushunish demak.
2. Nazariya — chuqur tushuntirish
2.1. FP ning asosiy g'oyalari
FP uch ustunga tayanadi:
- Pure functions (toza funksiyalar) — yon ta'sirsiz, bashoratli 2.3-bob.
- Immutability (o'zgarmaslik) — ma'lumotni buzmay, yangisini yasash 2.8-bob.
- Funksiyalar — qiymat (first-class, HOF) — funksiyalarni uzatish, qaytarish, birlashtirish 2.3-bob.
2.2. Pure function — toza funksiya (chuqur)
Toza funksiya ikki shartni bajaradi 2.3-bob:
- Determinizm — bir xil kirish doim bir xil chiqish 0.6-bob.
- Yon ta'sir (side effect) yo'q — tashqi olamga tegmaydi (global o'zgaruvchi, DOM, tarmoq, konsol, fayl).
// TOZA — faqat kirishga bog'liq, tashqariga tegmaydi
function qosh(a, b) { return a + b; }
function ikkilantir(arr) { return arr.map(x => x * 2); } // yangi massiv (2.7)
// NOTOZA — tashqi holatni o'zgartiradi (side effect)
let jami = 0;
function qoshDirty(x) { jami += x; } // global o'zgartiradi
function buzuq(arr) { arr.push(0); return arr; } // kirishni buzadi (2.7: mutating)
function vaqt() { return Date.now(); } // bir xil kirish, har xil chiqishNega toza yaxshi? Bashoratli (kirishni bilsangiz — chiqishni bilasiz), test qilishga oson (mock kerak emas), parallel-xavfsiz, debug oson, cache'lashga mos. Imkon qadar toza yozing.
Side effect kerak-ku? Ha — fayl yozish, tarmoq, DOM 2.16-bob — bularsiz dastur foydasiz. FP buni inkor etmaydi, balki side effect'larni ajratadi va cheklaydi: mantiq toza funksiyalarda, side effect chetda (masalan React'da
useEffect— 11.5).
Referential transparency (havola shaffofligi). Toza funksiyaning muhim xossasi: chaqiruvni uning natijasiga to'g'ridan almashtirish mumkin — kod ma'nosi o'zgarmaydi.
qosh(2, 3)har joyda5bilan teng, demak uni bemalol5ga almashtirsa bo'ladi. Bu — toza funksiya determinizmi va side effect yo'qligining bevosita oqibati. Foydasi: kompilyator/dvigatel kesh va optimallashtirishi (Math.random()notoza — almashtirib bo'lmaydi), inson uchun esa kod haqida fikrlash osonlashadi (qiymatni "joyiga qo'yib" o'qiy olasiz).
2.3. Immutability — o'zgarmaslik (chuqur)
Ma'lumotni o'zgartirmang — yangisini yarating 2.8-bob. Mutatsiya — yashirin bug'lar manbai 2.7-bob:
// MUTATSIYA — asl ma'lumotni buzadi
const arr = [1, 2, 3];
arr.push(4); // arr o'zgardi (2.7: mutating)
const user = { yosh: 19 };
user.yosh = 20; // obyekt buzildi
// IMMUTABLE — yangi yarat (2.7, 2.8)
const arr2 = [...arr, 4]; // yangi massiv (spread)
const yangilangan = { ...user, yosh: 20 }; // yangi obyekt
const ikki = arr.map(x => x * 2); // map — yangi (2.7)
const filtr = arr.filter(x => x > 1); // filter — yangiNega immutable? O'zgargan ma'lumotni "kim, qachon o'zgartirdi?" — javob berish qiyin (mutatsiya). Immutable'da — har o'zgarish yangi nusxa; eski saqlanadi (undo, time-travel — Redux DevTools), taqqoslash oson (React — o'zgardimi?
===bilan). React/Redux buni talab qiladi.
2.4. Higher-Order Functions (HOF) — chuqur
HOF — funksiyani argument sifatida oladi yoki qaytaradi (2.3, 2.6). FP'ning yuragi:
// 1) Funksiyani ARGUMENT sifatida (map/filter/reduce — 2.7)
[1, 2, 3].map(x => x * 2); // map — HOF (callback oladi)
// 2) Funksiyani QAYTARISH (closure — 2.4)
function kopaytuvchi(n) {
return (x) => x * n; // funksiya qaytaradi
}
const ikki = kopaytuvchi(2);
ikki(5); // 102.5. Composition — funksiyalarni birlashtirish
FP'da murakkab ish — kichik toza funksiyalarni birlashtirib (compose) yasaladi:
const toza = (s) => s.trim();
const kichik = (s) => s.toLowerCase();
const tireBilan = (s) => s.replaceAll(" ", "-");
// Qo'lda birlashtirish (ichma-ich)
const slug = (s) => tireBilan(kichik(toza(s)));
slug(" Salom Dunyo "); // "salom-dunyo"
// pipe — chapdan o'ngga "quvur" (o'qishliroq)
const pipe = (...fns) => (x) => fns.reduce((acc, fn) => fn(acc), x); // (2.7!)
const slug2 = pipe(toza, kichik, tireBilan);
slug2(" Salom Dunyo "); // "salom-dunyo"
// compose — o'ngdan chapga (matematik f(g(x)) tartibi)
const compose = (...fns) => (x) => fns.reduceRight((acc, fn) => fn(acc), x); // (2.7)
const slug3 = compose(tireBilan, kichik, toza); // o'ng tomondagi "toza" birinchi ishlaydi
slug3(" Salom Dunyo "); // "salom-dunyo"
pipe— ma'lumotni funksiyalar zanjiridan o'tkazish (2.7:.filter().map()zanjiriga o'xshash). Har funksiya bitta ish; birlashma — murakkab natija. Bu — FP'ning go'zalligi.
pipevscompose. Ikkalasi ham bir xil ishni qiladi, faqat o'qish yo'nalishi har xil:pipe(a, b, c)— chapdan o'ngga (abirinchi),compose(a, b, c)— o'ngdan chapga (cbirinchi, matematika(b(c(x)))tartibi). Amaldapipeo'qishliroq (yuqoridan pastga o'qilgandek), shuning uchun ko'p kutubxonalar (Lodash, Ramda) ikkalasini ham beradi.
Point-free (tacit) uslub. Diqqat qiling:
pipe(toza, kichik, tireBilan)da argument (syokix) umuman yozilmaydi — biz funksiyalarni nomma-nom ulaymiz, "ma'lumot qayerda?" deb ko'rsatmaymiz. Bu — point-free uslub ("point" = argument).const slug = (s) => tireBilan(kichik(toza(s)))esa argument-li (point-full). Point-free qisqa va shovqinsiz, lekin haddan oshsa o'qish qiyinlashadi (argument ko'rinmagani uchun) — muvozanat saqlang (5-bo'lim).
2.6. Deklarativ vs imperativ
- Imperativ — qanday qilishni aytasiz (qadamba-qadam: tsikl, o'zgaruvchi).
- Deklarativ — nima kerakligini aytasiz (FP uslubi).
// Imperativ — qanday (qadamba-qadam)
const juftKvadrat = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] % 2 === 0) juftKvadrat.push(arr[i] ** 2);
}
// Deklarativ — nima (FP — 2.7)
const juftKvadrat = arr.filter(x => x % 2 === 0).map(x => x ** 2);Deklarativ — qisqaroq, o'qishliroq, xato kamroq. FP deklarativ uslubni rag'batlantiradi.
2.7. Currying va partial application (ilg'or)
Currying — ko'p argumentli funksiyani bir argumentli funksiyalar zanjiriga aylantirish (2.4: closure):
// Oddiy
const qosh = (a, b) => a + b;
// Curried
const qoshCurried = (a) => (b) => a + b;
qoshCurried(5)(3); // 8
const beshGaQosh = qoshCurried(5); // partial — "5 ga qo'shuvchi"
beshGaQosh(3); // 8
beshGaQosh(10); // 15Foydasi: maxsus, qayta ishlatiladigan funksiyalar yaratish (closure — 2.4). React/kutubxonalarda uchraydi.
3. Asosiy tushunchalar — tez ma'lumotnoma
Pure function — determinizm + side effect yo'q 2.2-bob
Immutability — o'zgartirma, yangi yarat ([...], {...}, map/filter — 2.3)
HOF — funksiya oladi/qaytaradi 2.4-bob
Composition — kichik funksiyalarni birlashtirish (pipe — 2.5)
Deklarativ — "nima" (filter/map), "qanday" (tsikl) emas 2.6-bob
Currying — f(a)(b)(c) — bir argumentli zanjir (2.7)4. Batafsil kod namunalari
Misol 1 — Pure vs notoza (2.2)
// NOTOZA — global holat + mutatsiya
let savat = [];
function qoshDirty(mahsulot) { savat.push(mahsulot); } // side effect
// TOZA — yangi massiv qaytaradi (2.3)
function qosh(savat, mahsulot) { return [...savat, mahsulot]; }
function ochir(savat, id) { return savat.filter(m => m.id !== id); } // (2.7)
function yangila(savat, id, ozg) {
return savat.map(m => m.id === id ? { ...m, ...ozg } : m); // (2.7, 2.8)
}
// asl savat hech qachon o'zgarmaydi — har amal yangi nusxaMisol 2 — HOF va composition (2.4, 2.5)
const pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x); // (2.7)
const sonlar = [1, 2, 3, 4, 5, 6];
// Kichik toza funksiyalar
const juftlar = (arr) => arr.filter(n => n % 2 === 0);
const kvadrat = (arr) => arr.map(n => n ** 2);
const yigindi = (arr) => arr.reduce((a, b) => a + b, 0);
// Birlashtirish
const juftKvadratYigindi = pipe(juftlar, kvadrat, yigindi);
console.log(juftKvadratYigindi(sonlar)); // 2²+4²+6² = 4+16+36 = 56Misol 3 — Deklarativ ma'lumot qayta ishlash (2.6, 2.7)
const buyurtmalar = [
{ mahsulot: "Non", narx: 3000, soni: 2 },
{ mahsulot: "Sut", narx: 8000, soni: 1 },
{ mahsulot: "Olma", narx: 12000, soni: 3 },
];
// Deklarativ pipeline (toza, immutable — 2.7)
const jami = buyurtmalar
.map(b => b.narx * b.soni) // har biri jami
.filter(summa => summa > 5000) // 5000+
.reduce((a, b) => a + b, 0); // yig'indi
console.log(jami); // 8000 + 36000 = 44000Misol 4 — Currying (2.7)
// Curried — qayta ishlatiladigan validatorlar (2.13)
const minUzunlik = (min) => (matn) => matn.length >= min;
const maxUzunlik = (max) => (matn) => matn.length <= max;
const kamida8 = minUzunlik(8); // partial
const kopi20 = maxUzunlik(20);
console.log(kamida8("parol123")); // true
console.log(kopi20("juda uzun..."));// true/false
// Birlashtirib ishlatish
const validatorlar = [kamida8, kopi20];
const togriMi = (matn) => validatorlar.every(v => v(matn)); // (2.7)
console.log(togriMi("parol123")); // true5. To'g'ri va noto'g'ri holatlar
1) Mutatsiya (immutability buzilishi)
// asl ma'lumotni o'zgartirish (2.3, 2.7)
function qosh(arr, x) { arr.push(x); return arr; }
// yangi massiv
function qosh(arr, x) { return [...arr, x]; }2) Yashirin side effect
// funksiya ichida console/global/DOM (notoza — 2.2)
function hisobla(a, b) { const n = a + b; console.log(n); savat.push(n); return n; }
// toza — faqat hisob; side effect chetda
function hisobla(a, b) { return a + b; }3) Imperativ tsikl (deklarativ o'rniga)
// qo'lda tsikl (2.6)
let natija = [];
for (const x of arr) if (x > 0) natija.push(x * 2);
// deklarativ
const natija = arr.filter(x => x > 0).map(x => x * 2);4) Hamma narsani FP qilish (haddan oshirish)
// oddiy ishni murakkab compose/curry bilan
const f = pipe(g, compose(h, curry(k))); // o'qishsiz
// muvozanat — FP foydali joyda; oddiy joyda oddiy6. Keng tarqalgan xatolar va yechimlari
Xato 1 — Tasodifiy mutatsiya (React'da state buzilishi)
Sababi: push/sort/to'g'ridan tayinlash 2.7-bob. Yechimi: [...]/{...}/map/filter bilan yangi yarating 2.3-bob; React'da bu majburiy (11).
Xato 2 — Toza deb o'ylangan, lekin notoza funksiya
Sababi: ichida Date.now(), Math.random(), global, DOM 2.2-bob. Yechimi: bunday qiymatlarni argument sifatida uzating (toza qilish).
Xato 3 — reduce murakkablashib ketishi
Sababi: bitta reduceda juda ko'p mantiq. Yechimi: kichik funksiyalarga bo'ling, pipe bilan birlashtiring 2.5-bob.
Xato 4 — Performance (har render yangi massiv — React)
Sababi: immutability har safar yangi obyekt yaratadi. Yechimi: odatda muammo emas; kerak bo'lsa useMemo 11.6-bob bilan optimallashtiring.
Xato 5 — Composition tartibi chalkashligi
Sababi: compose (o'ngdan) vs pipe (chapdan) farqi. Yechimi: pipe ishlating (chapdan o'ngga — o'qishli, 2.5).
7. Integratsiya — bu mavzu stack'ning qayerida uchraydi
- Array metodlari 2.7-bob:
map/filter/reduce— FP'ning amaliy quroli. - Closure/HOF (2.3, 2.4): currying, funksiya qaytarish.
- React (11): komponent — toza funksiya; immutable state; props.
- Redux Toolkit 12.2-bob: reducer — toza funksiya; immutable yangilash (Immer bilan).
- Immutability 2.8-bob: spread, structuredClone.
- Test 8.11-bob: toza funksiyalar — test qilishga oson (mock kerak emas).
- TanStack Query 12.4-bob: deklarativ ma'lumot.
8. Eng yaxshi amaliyotlar (best practices)
- Imkon qadar toza funksiya yozing — mantiq toza, side effect chetda 2.2-bob.
- Immutability'ga rioya qiling —
push/mutatsiya o'rniga[...]/map/filter(2.3, 2.7). - Deklarativ uslub —
filter/maptsikl o'rniga 2.6-bob. - Kichik, bir vazifali funksiyalar —
pipebilan birlashtiring (2.5, 9.1). - Side effect'larni ajrating va cheklang (React:
useEffect— 11.5). - HOF bilan takrorlanishni kamaytiring 2.4-bob.
- Muvozanat — FP foydali joyda; OOP 2.10-bob bilan birga ishlatsa bo'ladi (haddan oshirmang — 5-bo'lim).
- Toza funksiyalarni alohida test qiling 8.11-bob.
9. Amaliy loyiha: "Funksional Ma'lumot Pipeline"
FP tamoyillarini to'liq ishlatadigan, toza va immutable ma'lumot qayta ishlash tizimi.
Maqsad
Pure functions, immutability, HOF va composition'ni amalda qo'llab, deklarativ, test qilishga oson kod yozish.
Talablar (requirements)
pipefunksiyasi:reducebilan (Misol 2) — barcha pipeline shu bilan.- Toza transformatsiya funksiyalari: har biri bitta ish (
filtrFaol,narxQosh,tartibla,formatla) — hech qaysi asl ma'lumotni o'zgartirmasin (2.2, 2.3). - Immutable CRUD:
qosh/ochir/yangila— yangi massiv qaytarsin (Misol 1); asl o'zgarmasligini isbotlang. - Composition: kamida 2 ta murakkab amalni
pipebilan kichik funksiyalardan yasang (Misol 2, 3). - HOF: kamida bitta funksiya qaytaruvchi funksiya (currying — masalan
filtrBuyuruvchi(shart)) (2.7, Misol 4). - Deklarativ pipeline: ma'lumot to'plamini (filtermapreduce) bilan tahlillang (Misol 3).
- Side effect ajratish: mantiq toza funksiyalarda; konsolga chiqarish/saqlash — alohida 2.2-bob.
- Test: har toza funksiyani bir xil kirishga bir xil chiqish berishini ko'rsating (determinizm).
Maslahatlar (hint)
pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x)(2.5, 2.7).- Toza: hech qaysi funksiya
push/global/console ishlatmasin (faqatreturn). - Immutable:
[...arr],{...obj},map/filter2.3-bob. - Currying:
const filtrBuyuruvchi = (shart) => (arr) => arr.filter(shart). - Determinizm isboti: bir funksiyani 2 marta bir xil kirish bilan chaqirib, natija bir xilligini ko'rsating.
"Tayyor" mezonlari (acceptance criteria)
-
pipeishlaydi va pipeline'larda qo'llangan. - Barcha transformatsiya funksiyalari toza (side effect yo'q).
- CRUD immutable (asl o'zgarmaydi — isbotlangan).
- Kamida 2 composition (
pipe) ishlatilgan. - Kamida bitta currying/HOF.
- Tahlil deklarativ pipeline bilan.
- Side effect mantiqdan ajratilgan.
- Toza funksiyalar determinizmi ko'rsatilgan.
Yechim kodi ataylab berilmagan — bu loyihani o'zingiz yozib ko'ring.
10. Xulosa va keyingi bobga ko'prik
Bu bobda toza, bashoratli kod uslubini — Functional Programmingni o'rgandik:
- FP uch ustun: pure functions (determinizm + side effect yo'q), immutability (yangi yarat — 2.7, 2.8), HOF (funksiya — qiymat — 2.3, 2.4).
- Composition (
pipe) — kichik toza funksiyalarni birlashtirib murakkab natija 2.7-bob. - Deklarativ (
filter/map) > imperativ (tsikl) — qisqa, o'qishli, xatosiz. - Currying —
f(a)(b)— qayta ishlatiladigan, sozlangan funksiyalar. - Best: mantiq toza, side effect chetda (React
useEffect); muvozanat (FP + OOP).
Keyingi bob — 2.16-bob: DOM — elementlarni tanlash, o'zgartirish, CRUD, events, event delegation, bubbling. Hozirgacha JS mantiqini o'rgandik; endi uni sahifaga ulaymiz! 0.5-bobda ko'rgan DOM (HTML'dan qurilgan daraxt) — JS bilan uni o'zgartirish, tugmaga javob berish — frontend'ning haqiqiy "joni". Bu — brauzerda interaktivlikning yuragi.
Eslatma va manbalar
- MDN Web Docs — first-class functions, pure functions, immutability tushunchalari
- Bu bob FP universal nazariyasiga (pure/immutable/HOF/composition) asoslangan; JS amaliyoti MDN Array/Function bilan bog'langan
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!