25 август 2025

Klass: asosiy sintaksis

Obyektga yo’naltirilgan dasturlashda klass – bu obyektlarni yaratish uchun kengaytiriladigan kod shabloni bo’lib, ularda dastlabki qiymatlarni (xususiyatlar) va xatti-harakatlarni (metodlar) amalga oshirishni belgilaydi.

Vikipediya

Amalda, biz ko’pincha foydalanuvchilar yoki tovarlar yoki boshqa narsalar kabi bir xil turdagi ko’plab obyektlarni yaratishimiz kerak.

Konstruktor, operator "new" bobidan allaqachon bilganimizdek, new function bunga yordam beradi.

Ammo zamonaviy JavaScript-da obyektga yo’naltirilgan dasturlash uchun foydali bo’lgan juda yangi xususiyatlarni taqdim etadigan yanada rivojlangan “klass” tuzilishi mavjud.

“Klass” sintaksisi

Asosiy sintaksis:

class MyClass {
  // klass metodlari
  constructor() { ... }
  method1() { ... }
  method2() { ... }
  method3() { ... }
  ...
}

Keyin new MyClass() ro’yxatdagi barcha metodlar bilan yangi obyekt yaratadi.

constructor() metodi avtomatik ravishda new tomonidan chaqiriladi, shuning uchun biz u yerda obyektni ishga tushirishimiz mumkin.

Masalan:

class User {
  constructor(name) {
    this.name = name;
  }

  sayHi() {
    alert(this.name);
  }
}

// Foydalanish:
let user = new User("John");
user.sayHi();

new User("John") chaqirilganda:

  1. Yangi obyekt yaratiladi.
  2. constructor berilgan argument bilan ishlaydi va unga this.name ni tayinlaydi.

…Keyin biz user.sayHi() kabi metodlarni chaqira olamiz.

Klass metodlari o’rtasida vergul yo’q

Yangi dasturchilar uchun odatiy tuzoq – bu sintaksis xatolariga olib keladigan klass metodlari orasida vergul qo’yishdir.

Bu yerdagi yozuvlarni obyektlar yozuvi bilan aralashtirish mumkin emas. Klass ichida vergul talab qilinmaydi.

Klass nima?

Xo’sh, aniq class nima? Bu o’ylashi mumkin bo’lgan til darajasidagi mutlaqo yangi obyekt emas.

Keling, barcha sehrni yo’qotaylik va aslida klass nima ekanligini ko’rib chiqaylik. Bu ko’plab murakkab jihatlarni tushunishda yordam beradi.

JavaScript-da klass funktsiyaning bir turi.

Mana, qarang:

class User {
  constructor(name) { this.name = name; }
  sayHi() { alert(this.name); }
}

// isbot: User bu funktsiya
alert(typeof User); // function

class User {...} konstruktsiyasi aslida nima qiladi:

  1. User nomli funktsiyani yaratadi, bu klass deklaratsiyasining natijasi bo’ladi.
    • Funktsiya kodi constructor metodidan olingan (agar biz bunday metodini yozmasak, bo’sh deb hisoblanadi).
  2. sayHi kabi barcha metodlarni User.prototype da saqlaydi.

Keyinchalik, yangi obyektlar uchun metodini chaqirganda, prototipdan olinadi, xuddi F.prototype bobida tasvirlanganidek. Shunday qilib, new User obyekti klass metodlariga kirish huquqiga ega.

Biz class User natijasini quyidagicha tasvirlashimiz mumkin:

Buni tekshirish uchun kod:

class User {
  constructor(name) {
    this.name = name;
  }
  sayHi() {
    alert(this.name);
  }
}

// klass bu funktsiya
alert(typeof User); // function

// ...yoki, aniqroq, konstruktor metodi
alert(User === User.prototype.constructor); // true

// metodlar User.prototype-da:
alert(User.prototype.sayHi); // alert(this.name);

// prototipda to'liq ikkita metod mavjud
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi

Faqat sintaksis shakar emas

Ba’zan odamlar class JavaScript-dagi “sintaksis shakar” deb aytishadi, chunki biz aslida class kalit so’zisiz bir xil narsani e’lon qilishimiz mumkin edi:

// sof funktsiyalarda class User qayta yozish

// 1. Konstruktor funktsiyasini yarating
function User(name) {
  this.name = name;
}
// har qanday funktsiya prototipi sukut bo'yicha konstruktor xususiyatiga ega,
// shuning uchun biz uni yaratishga hojat yo'q

// 2. Metodini prototipga qo'shing
User.prototype.sayHi = function () {
  alert(this.name);
};

// Foydalanish:
let user = new User("John");
user.sayHi();

Ushbu ta’rifning natijasi taxminan bir xil. Shunday qilib, konstruktorni prototip metodlari bilan birgalikda aniqlash uchun class sintaksis shakar deb hisoblanishining haqiqatan ham sabablari bor.

Garchi, muhim farqlar mavjud.

  1. Birinchidan, class tomonidan yaratilgan funktsiya maxsus ichki xususiyat bilan belgilanadi [[FunctionKind]]:"classConstructor". Shunday qilib, uni qo’lda yaratish bilan bir xil emas.

    Oddiy funktsiyadan farqli o’laroq, klass konstruktorini new siz chaqirish mumkin emas:

    class User {
      constructor() {}
    }
    
    alert(typeof User); // function
    User(); // Error: Class constructor User cannot be invoked without 'new'

    Shuningdek, aksariyat JavaScript interpretatorlarida klass konstruktorining matn vakilligi class... bilan boshlanadi.

    class User {
      constructor() {}
    }
    
    alert(User); // class User { ... }

    Boshqa farqlar ham bor, ularni tez orada ko’ramiz.

  2. Klass metodlarini sanab bo’lmaydi Klass ta’rifi "prototype" dagi barcha metodlar uchun enumerable bayroqni false ga o’rnatadi.

    Bu yaxshi, chunki agar biz obyekt uchun for..in ishlatsak, biz odatda uning klass metodlarini xohlamaymiz.

  3. Klasslar doimo use strict dan foydalanadi Klass konstruktsiyasidagi barcha kodlar avtomatik ravishda qat’iy rejimda bo’ladi.

Bundan tashqari, class sintaksisining asosiy ishlashidan tashqari, biz keyinroq o’rganadigan ko’plab boshqa xususiyatlarni ham taklif etadi.

Klass ifodalari

Xuddi funktsiyalar singari, klasslarni boshqa ifoda ichida aniqlash, ularni o’tkazish, qaytarish, tayinlash va h.k. mumkin.

Mana, klass ifodasiga misol:

let User = class {
  sayHi() {
    alert("Salom");
  }
};

Nomlangan funktsiya ifodalarga o’xshash, klass ifodasining nomi bo’lishi yoki bo’lmasligi mumkin.

Agar klass ifodasining nomi bo’lsa, u faqat klass ichida ko’rinadi:

// "Named Class Expression" (alas, bunday atama yo'q, lekin bu nima bo'layotgani)
let User = class MyClass {
  sayHi() {
    alert(MyClass); // MyClass nomi faqat klass ichida ko'rinadi
  }
};

new User().sayHi(); // ishlaydi, MyClass ta'rifini ko'rsatadi

alert(MyClass); // xato, MyClass nomi klassdan tashqarida ko'rinmaydi

Hatta klasslarni dinamik ravishda “talabga binoan” yaratishimiz mumkin, masalan:

function makeClass(phrase) {
  // klassni e'lon qiling va uni qaytaring
  return class {
    sayHi() {
      alert(phrase);
    }
  };
}

// Yangi klass yarating
let User = makeClass("Salom");

new User().sayHi(); // Salom

Getters/setters

Shuningdek, klasslar getter/setter, generator, hisoblash xususiyatlari va boshqalarni o’z ichiga oladi.

get/set yordamida amalga oshirilgan user.name uchun misol:

class User {

  constructor(name) {
    // setter ni chaqiradi
    this.name = name;
  }

  get name() {
    return this._name;
  }

  set name(value) {
    if (value.length < 4) {
      alert("Ism juda qisqa.");
      return;
    }
    this._name = value;
  }

}

let user = new User("John");
alert(user.name); // John

user = new User(""); // Ism juda qisqa.

Ichkarida, getter va setterlar User.prototype da yaratiladi.

Hisoblangan nomlar […]

Hisoblangan metod nomi bilan misol, kvadrat qavslar ichida:

class User {

  ['say' + 'Hi']() {
    alert("Salom");
  }

}

new User().sayHi();

Bunday xususiyatlar eslab qolinishi oson va simvollar uchun foydali.

Klass xususiyatlari

Eski brauzerlarda polifil kerak bo’lishi mumkin

Klass darajasidagi xususiyatlar tilga yaqinda qo’shilgan.

Yuqoridagi misolda User da faqat metodlar mavjud edi. Keling, xususiyat qo’shaylik:

class User {
  name = "Anonim";

  sayHi() {
    alert(`Salom, ${this.name}!`);
  }
}

new User().sayHi(); // Salom, Anonim!

Xususiyat User.prototype ga joylashtirilmagan. Buning o’rniga, u har bir obyekt uchun alohida, new tomonidan yaratiladi. Shunday qilib, xususiyat hech qachon bir klassning turli obyektlari o’rtasida taqsimlanmaydi.

Klass xususiyatlarining muhim farqi shundaki, ular User.prototype da emas, balki alohida obyektlarda o’rnatiladi:

class User {
  name = "John";
}

let user = new User();
alert(user.name); // John
alert(User.prototype.name); // undefined

Klass xususiyatlari bilan bog’langan metodlar yaratish

Funktsiyani bog'lash bobida ko’rsatilganidek, JavaScript-dagi funktsiyalar dinamik this ga ega. Bu chaqiruv kontekstiga bog’liq.

Shunday qilib, agar obyekt metodi boshqa kontekstda uzatilsa va chaqirilsa, this endi o’sha obyektga havola bo’lmaydi.

Masalan, bu kod undefined ni ko’rsatadi:

class Button {
  constructor(value) {
    this.value = value;
  }

  click() {
    alert(this.value);
  }
}

let button = new Button("salom");

setTimeout(button.click, 1000); // undefined

Muammo “this ni yo’qotish” deb ataladi.

Funktsiyani bog'lash bobida muhokama qilinganidek, buni tuzatishning ikkita yondashuvi bor:

  1. setTimeout(() => button.click(), 1000) kabi o’rash-funktsiyasini o’tkazish.
  2. Metodini obyektga bog’lash, masalan konstruktorda.

Klass xususiyatlari yana bir, juda oqlangan sintaksisni taqdim etadi:

class Button {
  constructor(value) {
    this.value = value;
  }
  click = () => {
    alert(this.value);
  }
}

let button = new Button("salom");

setTimeout(button.click, 1000); // salom

click = () => {...} klass xususiyati har bir Button obyektida alohida funktsiya yaratadi, ichida this shu obyektga havola qiladi. Biz button.click ni hamma joyga o’tkazishimiz mumkin va this ning qiymati har doim to’g’ri bo’ladi.

Bu ayniqsa brauzer muhitida, voqealar uchun tinglovchilar uchun foydali.

Xulosa

Asosiy klass sintaksisi quyidagicha:

class MyClass {
  prop = value; // xususiyat

  constructor(...) { // konstruktor
    // ...
  }

  method(...) {} // metod

  get something(...) {} // getter metod
  set something(...) {} // setter metod

  [Symbol.iterator]() {} // hisoblangan nom bilan metod (bu yerda simvol)
  // ...
}

MyClass texnik jihatdan funktsiya (biz constructor sifatida taqdim etadigan), metodlar, getter va setterlar esa MyClass.prototype ga yoziladi.

Keyingi boblarda biz klasslar haqida, jumladan meros va boshqa xususiyatlar haqida ko’proq bilib olamiz.

Vazifalar

Clock klassi (qum qutisiga qarang) funktsional uslubda yozilgan. Uni klass sintaksisida qayta yozing.

P.S. Konsolda soat chayqaladi, ko’rish uchun uni oching.

Vazifa uchun sandbox-ni oching.

class Clock {
  constructor({ template }) {
    this.template = template;
  }

  render() {
    let date = new Date();

    let hours = date.getHours();
    if (hours < 10) hours = "0" + hours;

    let mins = date.getMinutes();
    if (mins < 10) mins = "0" + mins;

    let secs = date.getSeconds();
    if (secs < 10) secs = "0" + secs;

    let output = this.template
      .replace("h", hours)
      .replace("m", mins)
      .replace("s", secs);

    console.log(output);
  }

  stop() {
    clearInterval(this.timer);
  }

  start() {
    this.render();
    this.timer = setInterval(() => this.render(), 1000);
  }
}

let clock = new Clock({ template: "h:m:s" });
clock.start();

Yechimni sandbox-da oching.

O'quv qo'llanma xaritasi

Izohlar

izoh berishdan oldin buni o'qing…
  • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
  • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
  • Bir nechta so'z so'zlarini kiritish uchun <code> yorlig'ini ishlating, bir nechta satrlar uchun - ularni <pre> yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen…)