Pure funksiyalar va Side Effects
Muammodan boshlaylik
let jami = 0;
function qoshish(son) {
jami += son; // ← tashqi o'zgaruvchini o'zgartiradi
return jami;
}
qoshish(5); // 5
qoshish(5); // 10 — bir xil argument, boshqa natija!
Bir xil argument — boshqa natija. Bu funksiyani test qilish, tushunish, qayta ishlatish qiyinlashadi. Pure funksiya bu muammoni hal qiladi.
Pure funksiya nima?
Pure funksiya — ikkita qoidaga amal qiladi:
- Bir xil argument → har doim bir xil natija
- Yon ta'sir (side effect) yo'q — tashqi hech narsani o'zgartirmaydi
// Pure funksiya
function qoshish(a, b) {
return a + b; // ← faqat parametrlarga bog'liq, hech narsani o'zgartirmaydi
}
qoshish(3, 5); // 8 — har doim
qoshish(3, 5); // 8 — har doim
Hayotiy o'xshatma
Kalkulyator. Siz "3 + 5" bosasangiz — har doim "8" chiqadi. Oldingi hisoblashlar ta'sir qilmaydi. Kalkulyator tashqi hech narsani o'zgartirmaydi — faqat hisoblaydi va ko'rsatadi.
Pure funksiya — dasturlashdagi kalkulyator.
Side Effect nima?
Side effect — funksiyaning o'z qaytish qiymatidan tashqari qiladigan har qanday ish:
// Side effect turlari:
function misol(x) {
console.log(x); // ← side effect: konsolga yozish
document.title = "Yangi"; // ← side effect: DOM o'zgartirish
globalVar = x; // ← side effect: tashqi o'zgaruvchi o'zgartirish
fetch("/api/log"); // ← side effect: tarmoq so'rovi
return x * 2;
}
Side effect — yomon emas. Dastur side effectsiz ishlamaydi — ma'lumot saqlanmaydi, ekranda hech narsa ko'rinmaydi. Lekin side effectlar nazorat ostida bo'lishi kerak.
Nima uchun pure funksiyalar yaxshi?
Bashorat qilish mumkin
// Pure — natijani oldindan bilasiz
const natija = qoshish(3, 5); // har doim 8
Test qilish oson
// Pure funksiyani test qilish — oddiy
test("qoshish to'g'ri ishlaydi", () => {
expect(qoshish(3, 5)).toBe(8);
expect(qoshish(-1, 1)).toBe(0);
});
// Hech qanday mock, setup kerak emas
Qayta ishlatish mumkin
Pure funksiya hech narsaga bog'liq emas — istalgan joyda ishlatiladi.
Impure funksiyalar — qachon muammo?
// Tashqi holatga bog'liq — impure
let chegirma = 0.1;
function narxHisoblash(narx) {
return narx * (1 - chegirma); // ← chegirma tashqarida
}
narxHisoblash(100); // 90
chegirma = 0.2;
narxHisoblash(100); // 80 — bir xil argument, boshqa natija!
Yechim — chegirmani parametr sifatida berish:
// Pure
function narxHisoblash(narx, chegirma) {
return narx * (1 - chegirma);
}
narxHisoblash(100, 0.1); // 90 — har doim
narxHisoblash(100, 0.2); // 80 — har doim
Massiv va ob'ektlar bilan ehtiyotkorlik
Massiv va ob'ektlar — reference type. Funksiya ichida o'zgartirilsa — tashqaridagi asl qiymat ham o'zgaradi:
// Impure — asl massivni o'zgartiradi
function birinchiniOchir(massiv) {
massiv.shift(); // ← asl massivni o'zgartiradi!
return massiv;
}
const sonlar = [1, 2, 3];
birinchiniOchir(sonlar);
console.log(sonlar); // [2, 3] — asl massiv o'zgardi!
Pure variant — yangi massiv qaytarish:
// Pure — yangi massiv qaytaradi
function birinchiniOchir(massiv) {
return massiv.slice(1); // ← yangi massiv, asl o'zgarmaydi
}
const sonlar = [1, 2, 3];
const yangi = birinchiniOchir(sonlar);
console.log(sonlar); // [1, 2, 3] — o'zgarmadi
console.log(yangi); // [2, 3]
Amalda qanday yozish kerak?
Hamma funksiyani pure qilish shart emas — lekin pure va impure ni ajratish kerak:
// Pure — hisoblash mantiq
function jami_hisoblash(buyurtmalar) {
return buyurtmalar.reduce((sum, b) => sum + b.narx, 0);
}
// Impure — side effect (ma'lumot olish, saqlash)
async function buyurtmalarniSaqla(buyurtmalar) {
const jami = jami_hisoblash(buyurtmalar); // ← pure funksiyani chaqiradi
await db.save({ buyurtmalar, jami });
}
Pure funksiyalar — mantiq uchun. Impure funksiyalar — tashqi dunyo bilan ishlash uchun.
Tez-tez uchraydigan xatolar
Ob'ektni to'g'ridan-to'g'ri o'zgartirish:
function yangilash(foydalanuvchi, yangiIsm) {
foydalanuvchi.ism = yangiIsm; // ❌ asl ob'ekt o'zgardi
return foydalanuvchi;
}
// ✅ yangi ob'ekt qaytarish
function yangilash(foydalanuvchi, yangiIsm) {
return { ...foydalanuvchi, ism: yangiIsm };
}
Tashqi o'zgaruvchiga bog'liqlik:
const soliq = 0.12;
function narx(asosiy) {
return asosiy * (1 + soliq); // ❌ tashqi soliq ga bog'liq
}
function narx(asosiy, soliq) {
return asosiy * (1 + soliq); // ✅ parametr sifatida
}
Xulosa
Pure funksiya — bir xil argument → har doim bir xil natija, side effect yo'q.
Side effect — tashqi o'zgaruvchi o'zgartirish, DOM, tarmoq, konsol. Yomon emas — lekin nazorat ostida bo'lishi kerak.
Pure funksiyalar — bashorat qilish mumkin, test qilish oson, qayta ishlatish mumkin.
Massiv va ob'ektlarni o'zgartirish o'rniga — yangi nusxa qaytariladi (slice, map, spread ...).
Keyingi dars
15-dars: Recursion — o'z-o'zini chaqirish