Class — static, getter, setter

~15 daq · JavaScript · OOP

Muammodan boshlaylik

Siz foydalanuvchilar tizimini yozyapsiz. Bir savol tug'ildi: tizimda hozir nechta foydalanuvchi bor?

Bu ma'lumot hech bir foydalanuvchiga tegishli emas. Jasurniki emas, Malikani ham emas — bu butun tizimning statistikasi. Agar har bir ob'ektga this.jami = ... qo'ysangiz, har birida alohida qiymat bo'ladi — umumiy hisoblagich bo'lmaydi.

Xuddi shu muammo getter va setter da ham bor: email xususiyatiga qiymat berilganda format tekshirilishi kerak, lekin oddiy this.email = qiymat hech narsani tekshirmaydi.

Bu uchta vazifani hal qilish uchun static, get, set kerak.


static — classning o'z xususiyati

Oddiy xususiyat ob'ektga tegishli — har bir ob'ektda o'z qiymati. static xususiyat esa classning o'ziga tegishli — barcha ob'ektlar uchun bitta.

Hayotiy o'xshatma

Maktabni tasavvur qiling. Har bir o'quvchining o'z sinfda o'rni, bahosi, ismi bor — bular o'quvchiga tegishli. Lekin "maktabda jami nechta o'quvchi bor?" — bu maktabning o'z ma'lumoti, birorta o'quvchiniki emas. Bir o'quvchi kelsa, maktab hisoblagichi oshadi. Ketsa — kamayadi. Bu hisoblagich — static.

class Foydalanuvchi {
  static soni = 0; // ← maktabning hisoblagichi kabi — classning o'zi saqlaydi

  constructor(ism) {
    this.ism = ism;
    Foydalanuvchi.soni++; // ← yangi o'quvchi keldi — hisoblagich oshdi
  }
}

const a = new Foydalanuvchi("Jasur");
const b = new Foydalanuvchi("Malika");

console.log(Foydalanuvchi.soni); // 2 — classdan o'qildi, ob'ektdan emas
console.log(a.soni);             // undefined — Jasurda bunday xususiyat yo'q

Nima uchun Foydalanuvchi.soni, this.soni emas?

this — ob'ektni ko'rsatadi. Lekin soni ob'ektda emas, classda. Shuning uchun this.soni ishlamaydi — Foydalanuvchi.soni deb class nomidan murojaat qilinadi.

Static metodlar ham xuddi shunday — new qilmasdan chaqiriladi:

class Foydalanuvchi {
  static soni = 0;

  constructor(ism) {
    this.ism = ism;
    Foydalanuvchi.soni++;
  }

  static statistika() {
    // ← bu metod hech bir ob'ektga tegishli emas
    console.log(`Tizimda ${Foydalanuvchi.soni} ta foydalanuvchi bor`);
  }
}

new Foydalanuvchi("Jasur");
new Foydalanuvchi("Malika");

Foydalanuvchi.statistika(); // "Tizimda 2 ta foydalanuvchi bor"

getter — o'qishda ishlaydigan funksiya

Ba'zan xususiyat aslida saqlanmaydi — har safar hisoblab beriladi. Yosh — tug'ilgan yildan hisoblash mumkin, alohida saqlashning hojati yo'q.

Hayotiy o'xshatma

Pasport. Ichida tug'ilgan sana yozilgan. Lekin siz "yoshim necha?" desangiz — pasport tug'ilgan sanadan hisoblab beradi. Yosh alohida yozilmagan — har safar hisob qilinadi. Getter — o'sha hisob.

class Odam {
  constructor(ism, tugilganYil) {
    this.ism         = ism;
    this.tugilganYil = tugilganYil;
    // yosh saqlanmaydi — har safar hisob qilinadi
  }

  get yosh() {
    return new Date().getFullYear() - this.tugilganYil;
  }
}

const jasur = new Odam("Jasur", 2000);

console.log(jasur.yosh); // 26 — hisoblab berdi, qavsiz, xususiyat kabi

jasur.yosh — qavsiz, xususiyat kabi ko'rinadi. Lekin aslida funksiya ishlaydi. tugilganYil o'zgarmasa ham, har yili yosh o'zgarib turadi — saqlanmaydi, hisoblanadi.

Nima uchun getter, oddiy metod emas?

Oddiy metod bo'lganda: jasur.yosh() — qavs bilan chaqiriladi. Getter: jasur.yosh — qavssiz, xususiyat kabi o'qiladi.

Bu faqat qulay yozuv emas. Getter "bu qiymat, saqlanmagan bo'lsa ham" degan ma'noni anglatadi. O'quvchi kodni ko'rganida — bu hisoblangan xususiyat ekanligini tushunadi.


setter — yozishda ishlaydigan funksiya

Xususiyatga qiymat berilganda biror narsa tekshirilishi yoki o'zgartirilishi kerak bo'lsa — setter.

Hayotiy o'xshatma

Pochta bo'limi. Siz xat yuborasiz — manzilni yozasiz. Pochta xodimi manzilni qabul qilishdan oldin tekshiradi: shahar bormi, ko'cha to'g'rimi, indeks mos keladimi. Noto'g'ri bo'lsa — qaytaradi. To'g'ri bo'lsa — qabul qiladi. Siz "manzil = ..." desangiz, pochta xodimi avtomatik tekshiradi. Setter — o'sha xodim.

class Foydalanuvchi {
  #email = ""; // ← xom saqlash joyi (tashqaridan ko'rinmaydi)

  constructor(ism, email) {
    this.ism   = ism;
    this.email = email; // ← setter chaqiriladi
  }

  get email() {
    return this.#email;
  }

  set email(qiymat) {
    // Pochta xodimi manzilni tekshiradi
    if (!qiymat.includes("@")) {
      throw new Error("Email @ belgisisiz bo'lmaydi");
    }
    this.#email = qiymat.toLowerCase().trim(); // ← tozalab saqlaydi
  }
}

const jasur = new Foydalanuvchi("Jasur", "  JASUR@Gmail.Com  ");
console.log(jasur.email); // "jasur@gmail.com" — setter tozaladi

jasur.email = "yangi@mail.com"; // ✅ setter tekshirdi, qabul qildi
jasur.email = "noto'g'ri";      // ❌ Error: Email @ belgisisiz bo'lmaydi

Nima uchun setter — validatsiyani constructor da qilmaslik?

Agar validatsiyani faqat constructor da yozsangiz — keyinchalik jasur.email = "xato" deb to'g'ridan o'zgartirsa, tekshirilmaydi. Setter — qayerdan o'zgartirilishidan qat'i nazar, har doim ishlaydi.


Faqat getter — o'qish uchun xususiyat

Setter yozmasangiz — xususiyat faqat o'qiladi, o'zgartirib bo'lmaydi:

class Doira {
  constructor(radius) {
    this.radius = radius;
  }

  get yuzasi() {
    return +(Math.PI * this.radius ** 2).toFixed(2);
  }
  // set yuzasi() — yo'q, demak yozib bo'lmaydi
}

const d = new Doira(5);
console.log(d.yuzasi); // 78.54
d.yuzasi = 100;        // jim o'tadi yoki strict modeda xato — lekin o'zgarmaydi

Tez-tez uchraydigan xatolar

static da this ni classning o'zi kabi ishlatish:

Static metodda this — class ning o'zini ko'rsatadi, ob'ektni emas. Shuning uchun this.soni va Foydalanuvchi.soni — bir xil, lekin faqat static metodda.

class Foydalanuvchi {
  static soni = 0;

  static statistika() {
    console.log(this.soni); // ✅ — static metodda this = Foydalanuvchi
  }

  koRsat() {
    console.log(this.soni); // ❌ undefined — oddiy metodda this = ob'ekt
    console.log(Foydalanuvchi.soni); // ✅ — aniq yozish yaxshiroq
  }
}

Getter ni funksiya kabi chaqirish:

Getter xususiyat kabi o'qiladi — qavslar yo'q. Qavs qo'yilsa — xato chiqadi.

class Misol {
  get qiymat() { return 42; }
}

const m = new Misol();
console.log(m.qiymat);   // 42 ✅
console.log(m.qiymat()); // ❌ TypeError: m.qiymat is not a function

Xulosa

static — classning o'z xususiyati yoki metodi. Barcha ob'ektlar uchun umumiy, new qilmasdan ClassName.xususiyat deb murojaat qilinadi.

get — o'qishda ishlaydigan funksiya. Xususiyat kabi ko'rinadi, lekin aslida hisoblaydi. Saqlash shart emas.

set — yozishda ishlaydigan funksiya. Qiymat berilganda avtomatik tekshiradi yoki o'zgartiradi. Validatsiya uchun ideal.


Keyingi dars

32-dars: Private maydonlar — # belgisi