Prototip va OOP
JavaScript prototip asosidagi til. Class sintaksisi syntactic sugar bo'lib, ostida hali ham prototype chain ishlaydi. this va call/apply/bind — OOP savollarining markazi.
Prototype chain — proto, Object.create
Nima bu?
Har bir JavaScript ob'ektining ichki `[[Prototype]]` (legacy: `__proto__`) havolasi bor — property topilmasa zanjir bo'ylab yuqoriga qarab qidiriladi. `Object.create(proto)` yangi ob'ekt yaratadi va uning prototipini belgilaydi. `Object.getPrototypeOf` va `Object.setPrototypeOf` zamonaviy API. Funksiyaning `prototype` property'si `new` bilan yaratilgan ob'ektlarning `[[Prototype]]` si bo'ladi.Gotcha: for...in prototip zanjiridagi enumerable property'larni ham aylanib chiqadi, shu sababli faqat o'z (own) property kerak bo'lsa Object.keys/hasOwnProperty bilan filtrlash shart. Shuningdek, Person.prototype.greet = fn — barcha instance'lar bitta umumiy funksiyani ishlatadi (xotira tejaydi), constructor ichida this.greet = fn esa har instance uchun alohida nusxa yaratadi — bu class metodlari va arrow field'lar orasidagi xotira farqiga ham asos bo'ladi.
Kod misoli
const animal = {
eat() {
console.log(`${this.name} ovqatlanmoqda`);
},
};
const dog = Object.create(animal);
dog.name = 'Rex';
dog.eat(); // 'Rex ovqatlanmoqda'
// Prototype zanjirini tekshirish
console.log(Object.getPrototypeOf(dog) === animal); // true
console.log(dog.hasOwnProperty('name')); // true
console.log(dog.hasOwnProperty('eat')); // false — prototipdan
function Person(name) {
this.name = name;
}
Person.prototype.greet = function () {
return `Salom, ${this.name}!`;
};
const ali = new Person('Ali');
console.log(ali.greet()); // 'Salom, Ali!'
console.log(ali.__proto__ === Person.prototype); // true (legacy)
Imtihonda
- Prototype chain qanday ishlaydi? `obj.prop` qidiruvi qanday amalga oshiriladi? - `Object.create(null)` nima uchun ishlatiladi? (toza dictionary, `hasOwnProperty` yo'q)Yodlash uchun
Property yo'q → `[[Prototype]]` zanjir bo'ylab yuqori → `null` da to'xtaydi.this — call, apply, bind
Nima bu?
`this` funksiya qanday chaqirilganiga bog'liq. `call` va `apply` funksiyani darhol chaqiradi va `this` ni birinchi argument sifatida beradi — `apply` argumentlarni massiv sifatida oladi. `bind` yangi funksiya qaytaradi, `this` doimiy bog'langan. Metodni ob'ektdan ajratib chaqirganda `this` yo'qoladi — shu yerda `bind` kerak bo'ladi.Muhim nuance: arrow funksiyaning this i lexical bo'lgani uchun call/apply/bind uni umuman o'zgartira olmaydi — arrow funksiyaga bind(obj) qo'llash sukut bo'yicha e'tiborsiz qoladi. Bu this mavzusi bilan arrow funksiyalar orasidagi eng ko'p adashtiriladigan farq.
Kod misoli
function introduce(greeting, punctuation) {
return `${greeting}, men ${this.name}${punctuation}`;
}
const user = { name: 'Diyor' };
introduce.call(user, 'Assalomu alaykum', '!');
// 'Assalomu alaykum, men Diyor!'
introduce.apply(user, ['Salom', '.']);
// 'Salom, men Diyor.'
const boundIntro = introduce.bind(user, 'Hey');
boundIntro('?'); // 'Hey, men Diyor?'
// this yo'qolish muammosi
const calculator = {
value: 0,
add(n) {
this.value += n;
return this;
},
};
const addFn = calculator.add;
// addFn(5); // xato — this undefined/window
const safeAdd = calculator.add.bind(calculator);
safeAdd(5);
console.log(calculator.value); // 5
Imtihonda
- `call`, `apply`, `bind` farqlari nima? - `const fn = obj.method; fn()` nima uchun ishlamaydi? Qanday tuzatish mumkin?Yodlash uchun
Darhol chaqirish — `call`/`apply`; keyinroq chaqirish — `bind`.Class sintaksisi — extends, super
Nima bu?
ES6 `class` — prototip asosidagi OOP uchun qulay sintaksis. `extends` meros olish, `super` ota class constructor yoki metodini chaqirish uchun. Static metodlar class'ning o'ziga tegishli. Private field (`#field`) va getter/setter ham qo'llab-quvvatlanadi. Angular component, service va directive'lar class sintaksisida yoziladi.Kod misoli
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} ovoz chiqaradi`;
}
static create(name) {
return new Animal(name);
}
}
class Dog extends Animal {
#breed; // private field
constructor(name, breed) {
super(name); // ota constructor chaqirilishi shart
this.#breed = breed;
}
speak() {
return `${super.speak()} — ${this.name} havlaydi (${this.#breed})`;
}
get breed() {
return this.#breed;
}
}
const rex = new Dog('Rex', 'Labrador');
console.log(rex.speak());
// 'Rex ovoz chiqaradi — Rex havlaydi (Labrador)'
console.log(Dog.create('Buddy') instanceof Animal); // true
Imtihonda
- `extends` qilganda constructor'da nima uchun `super()` chaqirish kerak? - Class va prototip (constructor function) farqi bormi?Yodlash uchun
`extends` → constructor'da birinchi `super()`; metod override → `super.method()`.