Class — asoslar, constructor, maydonlar

~20 daq · JavaScript · OOP

Muammodan boshlaylik

Oldingi darsda constructor funksiya va prototype ko'rdik:

function Foydalanuvchi(ism, email) {
  this.ism   = ism;
  this.email = email;
}

Foydalanuvchi.prototype.salomlash = function() {
  console.log(`Salom, ${this.ism}!`);
};

Foydalanuvchi.prototype.info = function() {
  console.log(`${this.ism} — ${this.email}`);
};

Bu ishlaydi. Lekin muammo: Foydalanuvchi va uning metodlari turli joylarda — constructor da, prototype da. Ko'rinish tarqoq. Yangi dasturchi kodga qaraydi — tuzilmani tushunish qiyin.

Class — constructor va prototype ni bitta joyga yig'ib, aniq yozuv beradi. Ichki mexanizm o'zgarmaydi — faqat sintaksis yangi.


Class sintaksisi

class Foydalanuvchi {
  constructor(ism, email) {
    this.ism   = ism;
    this.email = email;
  }

  salomlash() {
    console.log(`Salom, ${this.ism}!`);
  }

  info() {
    console.log(`${this.ism} — ${this.email}`);
  }
}

const jasur = new Foydalanuvchi("Jasur", "jasur@mail.com");
jasur.salomlash(); // "Salom, Jasur!"

Hayotiy o'xshatma

Bino loyihasi (blueprint). Loyihada: xonalar soni, ularning joylashuvi, qanday jihozlar bo'lishi. Bir loyihadan yuzlab xuddi shunday binolar quriladi. class — o'sha loyiha. new — loyiha asosida bino qurish.


constructor — ob'ekt yaratilganda

constructor — new chaqirilganda avtomatik ishlaydigan maxsus metod. Ob'ektning boshlang'ich qiymatlarini o'rnatish uchun.

class Avtomobil {
  constructor(model, yil, rang) {
    this.model = model;
    this.yil   = yil;
    this.rang  = rang;
    this.tezlik = 0; // ← har doim 0 dan boshlanadi
  }
}

const nexia = new Avtomobil("Nexia 3", 2022, "oq");
console.log(nexia.model);   // "Nexia 3"
console.log(nexia.tezlik);  // 0

constructor bo'lmasa — JavaScript ichki bo'sh constructor qo'shadi:

class Bo_sh {}
const ob = new Bo_sh(); // ishlaydi, ob = {}

Metodlar

Class ichidagi metodlar avtomatik prototype ga qo'shiladi — xotira tejash xususiyati saqlanadi.

class Hisoblagich {
  constructor(boshlanish = 0) {
    this.son = boshlanish;
  }

  oshir()  { this.son++; }
  kamayt() { this.son--; }
  nol()    { this.son = 0; }

  qiymat() {
    return this.son;
  }
}

const h = new Hisoblagich(10);
h.oshir();
h.oshir();
h.kamayt();
console.log(h.qiymat()); // 11

Class maydoni (class field)

ES2022 dan boshlab xususiyatlarni constructor siz ham e'lon qilish mumkin:

class Foydalanuvchi {
  // Class maydoni — constructor siz
  rol   = "user";      // ← har ob'ektda "user" bo'lib boshlanadi
  faol  = true;
  kirish_soni = 0;

  constructor(ism, email) {
    this.ism   = ism;
    this.email = email;
  }

  kirish() {
    this.kirish_soni++;
    console.log(`${this.ism} kirdi. Jami: ${this.kirish_soni}`);
  }
}

const jasur = new Foydalanuvchi("Jasur", "jasur@mail.com");
console.log(jasur.rol);          // "user"
console.log(jasur.kirish_soni);  // 0

jasur.kirish(); // "Jasur kirdi. Jami: 1"
jasur.kirish(); // "Jasur kirdi. Jami: 2"

Static metodlar va xususiyatlar

static — ob'ektga emas, class ning o'ziga tegishli. new qilmasdan chaqiriladi.

class MathUtil {
  static PI = 3.14159;

  static aylana_yuzasi(radius) {
    return MathUtil.PI * radius * radius;
  }

  static juftmi(n) {
    return n % 2 === 0;
  }
}

console.log(MathUtil.PI);               // 3.14159
console.log(MathUtil.aylana_yuzasi(5)); // 78.53975
console.log(MathUtil.juftmi(4));        // true

// new qilishning hojati yo'q:
const m = new MathUtil();
m.juftmi(4); // ❌ TypeError: m.juftmi is not a function

Static metodlar qachon? Ob'ektning holati (state) kerak bo'lmagan yordamchi funksiyalar uchun.


getter va setter

get va set — xususiyatga o'qish va yozishni boshqarish.

class Doira {
  constructor(radius) {
    this._radius = radius; // ← _ belgisi: "to'g'ridan-to'g'ri o'zgartirmang"
  }

  get radius() {
    return this._radius;
  }

  set radius(qiymat) {
    if (qiymat <= 0) throw new Error("Radius musbat bo'lishi kerak");
    this._radius = qiymat;
  }

  get yuzasi() {
    return Math.PI * this._radius ** 2; // ← hisoblab qaytaradi
  }
}

const d = new Doira(5);
console.log(d.radius); // 5   ← getter, xuddi xususiyat kabi o'qiladi
console.log(d.yuzasi); // 78.53...

d.radius = 10;         // ← setter chaqirildi
d.radius = -1;         // ❌ Error: Radius musbat bo'lishi kerak

Tez-tez uchraydigan xatolar

Metodlar orasiga vergul qo'yish:

class Xato {
  salomlash() { console.log("salom"); },  // ❌ SyntaxError — vergul qo'yilmaydi
  xayrlash()  { console.log("xayr"); }
}

class Togri {
  salomlash() { console.log("salom"); }   // ✅ — vergulsiz
  xayrlash()  { console.log("xayr"); }
}

this ni arrow function bilan metod yozish:

class Hisoblagich {
  son = 0;

  // ❌ — prototype ga emas, har ob'ektga alohida nusxa
  oshir = () => { this.son++; }

  // ✅ — prototype da, xotira tejaldi
  oshir() { this.son++; }
}

Lekin event handler larda arrow field foydali — this saqlanadi:

class Tugma {
  son = 0;

  // ✅ event handler sifatida — this saqlanadi
  bosish = () => {
    this.son++;
    console.log(this.son);
  };
}

const t = new Tugma();
document.addEventListener("click", t.bosish); // this = t ✅

Xulosa

class — constructor funksiya va prototype ni qulay yozuvga o'rab beradi. Mexanizm o'zgarmaydi.

class Nomi {
  maydon = qiymat;           // class field — har ob'ektda alohida

  constructor(arg) {         // ob'ekt yaratilganda ishlaydi
    this.xususiyat = arg;
  }

  metod() { }                // prototype da — hammada umumiy

  static yordamchi() { }     // class ning o'ziga tegishli, ob'ektga emas

  get xususiyat() { }        // o'qishni boshqarish
  set xususiyat(q) { }       // yozishni boshqarish
}

Keyingi dars

30-dars: Class — extends va super