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.
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:
- Yangi obyekt yaratiladi.
constructorberilgan argument bilan ishlaydi va ungathis.nameni tayinlaydi.
…Keyin biz user.sayHi() kabi metodlarni chaqira olamiz.
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:
Usernomli funktsiyani yaratadi, bu klass deklaratsiyasining natijasi bo’ladi.- Funktsiya kodi
constructormetodidan olingan (agar biz bunday metodini yozmasak, bo’sh deb hisoblanadi).
- Funktsiya kodi
sayHikabi barcha metodlarniUser.prototypeda 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.
-
Birinchidan,
classtomonidan 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
newsiz 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.
-
Klass metodlarini sanab bo’lmaydi Klass ta’rifi
"prototype"dagi barcha metodlar uchunenumerablebayroqnifalsega o’rnatadi.Bu yaxshi, chunki agar biz obyekt uchun
for..inishlatsak, biz odatda uning klass metodlarini xohlamaymiz. -
Klasslar doimo
use strictdan 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
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:
setTimeout(() => button.click(), 1000)kabi o’rash-funktsiyasini o’tkazish.- 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.
Izohlar
<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…)