OOP ustuni: Encapsulation (inkapsulyatsiya), xususiy ma'lumotlarni himoyalash, # private fieldlar, _ convention cheklovlari hamda dinamik hisoblangan getter/setterlar.
Bu bobda OOP'ning to'rtinchi asosiy ustuni — Encapsulationni, va uni Chapter 22'da ko'rgan Getter/Setter va Private Field'lar bilan qanday amalga oshirishni chuqur o'rganamiz.
Encapsulation (inkapsulyatsiya) — ma'lumot (data) va uni boshqaruvchi metodlarni bitta joyda birlashtirish, hamda ma'lumotning ichki tuzilishini tashqi dunyodan "yashirish".
Agar object'ning barcha propertylari to'g'ridan-to'g'ri o'zgartirilaversa, dastur ichida nazoratsiz, noto'g'ri qiymatlar paydo bo'lishi mumkin. Encapsulation — ma'lumotni faqat "nazorat qilingan eshiklar" (metodlar) orqaligina o'zgartirishga majbur qiladi.
🚗 Mashina dvigatelini tasavvur qiling: haydovchi dvigatelning ichki mexanizmini bilishi shart emas va unga to'g'ridan-to'g'ri tegishi mumkin emas — u faqat "interfeys" (gaz pedali, rul) orqali mashinani boshqaradi. Dvigatelning o'zi — inkapsulyatsiya qilingan.
script.jsJavaScriptclass BankAccount {constructor(balance) {this.balance = balance;}}let account = new BankAccount(1000);account.balance = -5000; // ❌ Hech qanday tekshiruvsiz, noto'g'ri qiymat!console.log(account.balance); // -5000
Bu yerda hech narsa balancening manfiy bo'lishining oldini olmayapti — chunki balance to'g'ridan-to'g'ri, hech qanday nazoratsiz o'zgartirilishi mumkin.
⚠️ Common Mistake
Barcha propertylarni ochiq (public) qilib qo'yish — kichik loyihalarda muammo tug'dirmasligi mumkin, lekin katta loyihalarda bu "har kim, har qanday joydan, har qanday noto'g'ri qiymat bilan ma'lumotni buzishi mumkin" degani.
script.jsJavaScriptclass BankAccount {#balance;constructor(initialBalance) {if (initialBalance < 0) {throw new Error("Boshlang'ich balans manfiy bo'lishi mumkin emas");}this.#balance = initialBalance;}get balance() {return this.#balance;}deposit(amount) {if (amount <= 0) {throw new Error("Depozit summasi musbat bo'lishi kerak");}this.#balance += amount;}withdraw(amount) {if (amount > this.#balance) {throw new Error("Balansda yetarli mablag' yo'q");}this.#balance -= amount;}}let account = new BankAccount(1000);account.deposit(500);console.log(account.balance); // 1500account.withdraw(3000); // ❌ Error: Balansda yetarli mablag' yo'q
#balance — private field, class tashqarisidan mutlaqo ko'rinmaydi va o'zgartirilmaydi.get balance() — faqat o'qish uchun "eshik" ochadi (o'zgartirish uchun emas).deposit(), withdraw() — #balanceni o'zgartirishning yagona yo'li, va ularning ichida tekshiruv (validation) mavjud.code.textTEXTTashqi dunyo│▼ (faqat metodlar orqali)┌─────────────────────┐│ BankAccount ││ ││ #balance (yashirin) │ ← to'g'ridan-to'g'ri kirib bo'lmaydi│ ││ deposit() ────┐ ││ withdraw() ─────┼──→│ #balance│ get balance() ──┘ │└─────────────────────┘
🔥 Important
Bu naqsh — Chapter 18'da o'rgangan Error Handling bilan Encapsulation'ning birgalikda ishlashiga aniq misol: noto'g'ri qiymat kiritilishga urinilganda, tizim buni jimgina qabul qilish o'rniga aniq xatolik bilan rad etadi.
# bilan private field'lar nisbatan yangi (ES2022). Undan oldin, dasturchilar "private"ni faqat kelishuv (convention) orqali — property nomi oldiga pastki chiziq (_) qo'yib — ifodalashgan.
script.jsJavaScriptclass OldStyleAccount {constructor(balance) {this._balance = balance; // "men private bo'lishni xohlayman" degan ishora}get balance() {return this._balance;}}let acc = new OldStyleAccount(500);console.log(acc._balance); // 500 — LEKIN bu ishlaydi!acc._balance = -1000; // Bu ham "ishlaydi", garchi noto'g'ri bo'lsa ham
_balance — bu shunchaki oddiy property, faqat oldida _ bor. JavaScript uni haqiqiy private sifatida bloklamaydi — bu faqat boshqa dasturchilarga "bu propertyga tashqaridan tegmang" degan kelishuv (convention), lekin texnik jihatdan hech kim buni bloklamaydi.
| Usul | Chinakam private? | Qachon ishlatiladi |
|---|---|---|
_balance (pastki chiziq) | ❌ Yo'q, faqat kelishuv | Eski kodlarda, yoki # qo'llab-quvvatlanmagan muhitlarda |
#balance (private field) | ✅ Ha, texnik jihatdan bloklangan | Zamonaviy kodda tavsiya etiladi |
💡 Key Idea
Zamonaviy loyihalarda har doim # ishlatish tavsiya etiladi — u haqiqiy xavfsizlikni ta'minlaydi, _ esa faqat "yaxshi niyat"ga tayanadi.
Encapsulation faqat "himoya qilish" uchun emas, balki propertyni boshqa ma'lumotlar asosida dinamik hisoblash uchun ham ishlatiladi.
script.jsJavaScriptclass Person {constructor(firstName, lastName) {this.firstName = firstName;this.lastName = lastName;}get fullName() {return `${this.firstName} ${this.lastName}`;}set fullName(value) {let parts = value.split(" ");this.firstName = parts[0];this.lastName = parts[1];}}let person = new Person("Ali", "Valiyev");console.log(person.fullName); // "Ali Valiyev"person.fullName = "Vali Karimov";console.log(person.firstName); // "Vali"console.log(person.lastName); // "Karimov"
fullName — hech qayerda alohida saqlanmaydi, u har safar firstName va lastNamedan hisoblanadi (getter), va o'rnatilganda (setter) ularni avtomatik yangilaydi.
Task:
#age (private field) bilan Person class yarating, get age() orqali uni o'qish imkonini bering, lekin tashqaridan to'g'ridan-to'g'ri o'zgartirib bo'lmasin.
Required Concepts:
get age() yozing, set age() yozmang — shunda u faqat o'qish uchun bo'ladi.Task:
Temperature class yarating — #celsius private field bilan. get fahrenheit() getter qo'shing, u Celsius'ni Fahrenheitga aylantirib bersin (F = C * 9/5 + 32). set celsius(value) orqali faqat -273dan katta qiymatlar qabul qilinsin (aks holda xatolik).
Required Concepts:
set celsius(value) { if (value < -273) throw new Error(...); this.#celsius = value; }Task:
To'liq ShoppingCart class yarating: #items (private array). addItem(name, price), removeItem(name) metodlari, get total() getter (barcha narxlar yig'indisi), get itemCount() getter (mahsulotlar soni). Barcha metodlarga tegishli tekshiruvlar (validation) qo'shing.
Required Concepts:
#items — object'lar array'i bo'lsin: { name, price }.script.jsJavaScriptclass Wallet {#amount = 0;add(value) {this.#amount += value;}get amount() {return this.#amount;}}let wallet = new Wallet();wallet.add(100);wallet.amount = 500; // to'g'ridan-to'g'ri o'zgartirishga urinishconsole.log(wallet.amount);
🧠 Think first! Javobni ko'rishdan oldin kamida 30 soniya o'ylang.
<details> <summary>Answer</summary> 100Why?
Wallet class'ida faqat get amount() bor, set amount() yo'q. Shuning uchun wallet.amount = 500 — jimgina e'tiborga olinmaydi (strict mode'da bo'lmasa xatolik ham bermaydi), chunki bu property faqat o'qish uchun (read-only). #amountning haqiqiy qiymati — faqat add() metodi orqali o'zgargan, u 100ga teng qolgan.
Quyidagi kodda muammo bor:
script.jsJavaScriptclass User {constructor(email) {this.email = email;}set email(value) {if (!value.includes("@")) {throw new Error("Email formati noto'g'ri");}this.email = value;}}let user = new User("test@example.com");
Your Task:
Yechim: Ichki saqlash uchun boshqa nom (#_email yoki _email) ishlatish kerak:
</details>script.jsJavaScriptclass User {#email;constructor(email) {this.email = email; // setterni chaqiradi}set email(value) {if (!value.includes("@")) {throw new Error("Email formati noto'g'ri");}this.#email = value;}get email() {return this.#email;}}let user = new User("test@example.com");console.log(user.email); // "test@example.com"
# bilan private field'lar — chinakam, texnik jihatdan himoyalangan yashirish._ bilan boshlanuvchi nomlar — faqat kelishuv, haqiqiy himoya emas.# (private field) ishlating, _ emas.get yozib, set yozmaslik — propertyni "faqat o'qish uchun" qiladi.script.jsJavaScriptclass Account {#balance;constructor(balance) {this.#balance = balance;}get balance() {return this.#balance;}deposit(amount) {if (amount <= 0) throw new Error("Noto'g'ri summa");this.#balance += amount;}}
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: