25 август 2025

F.prototype

Esingizda bo’lsin, yangi obyektlar new F() kabi konstruktor funktsiyasi bilan yaratilishi mumkin.

Agar F.prototype obyekt bo’lsa, u holda new operator undan yangi obyekt uchun [[Prototype]] ni o’rnatishda foydalanadi.

Esda tuting:

Javascript boshidan prototip merosga ega edi. Bu tilning asosiy xususiyatlaridan biri edi.

Ammo qadimgi vaqtlarda unga to’g’ridan-to’g’ri kirish imkoni yo’q edi. Ishonchli ishlaydigan yagona narsa, ushbu bobda tasvirlangan konstruktor funktsiyasining "prototype" vxususiyati edi. Shunday qilib, uni ishlatadigan ko’plab skriptlar mavjud

Iltimos e’tibor bering, F.prototype bu yerda F da "prototype" nomli odatiy xususiyatni anglatadi. Bu “prototype” atamasiga o’xshash bir narsaga o’xshaydi, ammo bu yerda biz haqiqatan ham ushbu nomga ega odatiy xususiyatni nazarda tutamiz.

Mana misol:

let animal = {
  eats: true
};

function Rabbit(name) {
  this.name = name;
}

Rabbit.prototype = animal;

let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal

alert( rabbit.eats ); // true

Rabbit.prototype = animal sozlamasida so’zma-so’z quyidagicha ifodalanadi: “new Rabbit yaratilganda, uning [[Prototype]] ni animal ga belgilang”.

Natijada paydo bo’lgan rasm:

Rasmda "prototype" – gorizontal o’q, odatiy xususiyatni anglatadi va [[Prototype]] vertikal bo’lib, rabbit ning animal dan merosxo’rligini anglatadi.

F.prototypefaqatnew Fvaqtida ishlatiladi

Agar yaratilgandan so’ng, F.prototype xususiyati o’zgarsa (F.prototype = <another object>) bo’lsa, unda new F tomonidan yaratilgan yangi obyektlar [[Prototype]] nomli boshqa obyektga ega bo’ladi, lekin allaqachon mavjud narsalar eskisini saqlab qoladi.

Sukut bo’yicha F.prototype, constructor xususiyat

Har qanday funktsiya "prototype" xususiyatiga ega, hatto biz uni ta’minlamasak ham.

Odatiy "prototype" funktsiyani o’zi ko’rsatadigan yagona constructor xususiyatiga ega bo’lgan obyekt.

Shunga o’xshash:

function Rabbit() {}

/* standart prototip
Rabbit.prototype = { constructor: Rabbit };
*/

Biz buni tekshirib ko’rishimiz mumkin:

function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }

alert(Rabbit.prototype.constructor == Rabbit); // true

Tabiiyki, agar biz hech narsa qilmasak, constructor xususiyati barcha quyonlarga [[Prototype]] orqali mavjud:

function Rabbit() {}
// by default:
// Rabbit.prototype = { constructor: Rabbit }

let rabbit = new Rabbit(); // {constructor: Rabbit} dan meros

alert(rabbit.constructor == Rabbit); // true (prototipdan)

Mavjud bilan bir xil konstruktor yordamida yangi obyekt yaratish uchun constructor xususiyatidan foydalanishimiz mumkin.

Buy erda bo’lgani kabi:

function Rabbit(name) {
  this.name = name;
  alert(name);
}

let rabbit = new Rabbit("White Rabbit");

let rabbit2 = new rabbit.constructor("Black Rabbit");

Obyektga ega bo’lganimizda, buning uchun qaysi konstruktor ishlatilganligini bilmasak (masalan, u uchinchi tomon kutubxonasidan kelib chiqadi) va biz yana bir xilini yaratishimiz kerak bo’lsa bu juda qulay.

Ehtimol, "constructor" haqida eng muhim narsa shu…

…JavaScript o’zi to’g’ri "constructor" qiymatini ta’minlamaydi.

Ha, bu funktsiyalar uchun standart "prototype" da mavjud, ammo barchasi shu. Keyinchalik u bilan nima sodir bo’ladi – bu butunlay bizdadir.

Xususan, agar biz standart prototipni umuman almashtirsak, unda unda "constructor" bo’lmaydi.

Masalan:

function Rabbit() {}
Rabbit.prototype = {
  jumps: true
};

let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false

Shunday qilib, to’g’ri "constructor" ni saqlab qolish uchun biz "prototype" ga yozish o’rniga xususiyatlarni qo’shish/o’chirishni tanlashimiz mumkin:

function Rabbit() {}

// Rabbit.prototype-ni to'liq yozib bo'lmaydi
// shunchaki qo'shib qo'ying
Rabbit.prototype.jumps = true;
// standart Rabbit.prototype.constructor saqlanib qoladi

Yoki, muqobil ravishda, constructor xususiyatini qo’lda qayta yarating:

Rabbit.prototype = {
  jumps: true,
  constructor: Rabbit
};

// endi ham konstruktor to'g'ri, chunki biz uni qo'shdik

Xulosa

Ushbu bobda biz konstruktor funktsiyasi orqali yaratilgan obyektlar uchun [[Prototype]] ni o’rnatish usulini qisqacha bayon qildik. Keyinchalik biz unga tayanadigan yanada rivojlangan dasturlash shablonlarni ko’rib chiqamiz.

Hammasi juda sodda, tushunarli bo’lishi uchun bir nechta eslatma:

  • F.prototype xususiyati [[Prototype]] bilan bir xil emas. F.prototype qiladigan yagona narsa: new F() chaqirilganda yangi obyektlarning [[Prototype]] ni o’rnatadi.
  • F.prototype qiymati obyekt yoki null bo’lishi kerak: boshqa qiymatlar ishlamaydi.
  • "prototype" xususiyati faqat konstruktor funktsiyasiga o’rnatilganda va new bilan chaqirilganda bunday maxsus ta’sirga ega bo’ladi.

Oddiy obyektlarda prototype alohida ahamiyatga ega emas:

let user = {
  name: "John",
  prototype: "Bla-bla", // hech qanday sehr yo'q
};

Odatiy bo’lib, barcha funktsiyalarda F.prototype = {constructor: F} mavjud, shuning uchun biz obyektning konstruktorini uning "constructor" xususiyatiga kirish orqali olishimiz mumkin.

Vazifalar

Quyidagi kodda biz new Rabbit ni yaratamiz va keyin uning prototipini o’zgartirishga harakat qilamiz.

Boshida bizda ushbu kod mavjud:

function Rabbit() {}
Rabbit.prototype = {
  eats: true,
};

let rabbit = new Rabbit();

alert(rabbit.eats); // true
  1. Biz yana bitta matn qo’shdik (ta’kidlangan), hozir qanday alert ko’rsatilmoqda?

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    Rabbit.prototype = {};
    
    alert( rabbit.eats ); // ?
  2. …Va agar kod shunga o’xshash bo’lsa (bitta satr o’rni o’zgartirildi)?

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    Rabbit.prototype.eats = false;
    
    alert( rabbit.eats ); // ?
  3. Bu kabi (bitta satr o’rni o’zgartirildi)?

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    delete rabbit.eats;
    
    alert( rabbit.eats ); // ?
  4. Oxirgi variant:

    function Rabbit() {}
    Rabbit.prototype = {
      eats: true
    };
    
    let rabbit = new Rabbit();
    
    delete Rabbit.prototype.eats;
    
    alert( rabbit.eats ); // ?

Javoblar:

  1. true.

    Rabbit.prototype ga topshirish yangi obyektlar uchun [[Prototype]] ni o’rnatadi, ammo bu mavjudlariga ta’sir qilmaydi.

  2. false.

    Obyektlar havola orqali tayinlanadi. Rabbit.prototype obyekti takrorlanmagan, u hali ham bitta obyektga Rabbit.prototype va rabbit ning [[Prototype]] tomonidan havola qilinadi.

    Shunday qilib, uning mazmunini bitta havola orqali o’zgartirganda, ikkinchisi orqali ko’rinadi.

  3. true.

    Barcha o'chirish operatsiyalari to’g’ridan-to’g’ri obyektga qo’llaniladi. Bu yerda rabbit.eats faylini rabbit dan olib tashlashga harakat qiladi, lekin unda yo’q. Shunday qilib, operatsiya hech qanday ta’sir qilmaydi.

  4. undefined.

    Prototipdan eats xususiyati o’chirildi, endi u mavjud emas.

Tasavvur qiling, bizda konstruktor funktsiyasi tomonidan yaratilgan obj tasodif obyekti bor – qaysi biriligini bilmaymiz, lekin undan foydalanib yangi obyekt yaratmoqchimiz.

Biz buni shunday qila olamizmi?

let obj2 = new obj.constructor();

Bunday kodni to’g’ri ishlashiga imkon beradigan obj uchun konstruktor funktsiyasiga misol keltiring. Va uni noto’g’ri ishlashga olib keladigan misol.

Agar "constructor" xususiyati to’g’ri qiymatga ega ekanligiga amin bo’lsak, bunday yondashuvdan foydalanishimiz mumkin.

Masalan, standart "prototype" ga tegmasak, u holda ushbu kod aniq ishlaydi:

function User(name) {
  this.name = name;
}

let user = new User("John");
let user2 = new user.constructor("Pete");

alert(user2.name); // Pete (ishladi!)

Bu ishladi, chunki User.prototype.constructor == User.

…Ammo agar kimdir, masalan, User.prototype ning ustiga yozsa va "constructor" ni qayta yaratishni unutsa, u holda bu muvaffaqiyatsiz bo’ladi.

Masalan:

function User(name) {
  this.name = name;
}
User.prototype = {}; // (*)

let user = new User('John');
let user2 = new user.constructor('Pete');

alert( user2.name ); // undefined

Nega user2.name undefined?

new user.constructor("Pete") qanday ishlashi:

  1. Birinchidan, u user da constructor ni qidiradi. Hech narsa yo’q.
  2. Keyin u prototip zanjiriga amal qiladi. user prototipi User.prototype dir va unda ham hech narsa yo’q.
  3. User.prototype ning qiymati {} oddiy obyekt bo’lib, uning prototipi Object.prototype dir. Va Object.prototype.constructor == Object mavjud. Shunday qilib u ishlatiladi.

Oxir-oqibat, bizda let user2 = new Object('Pete') bor. O’rnatilgan Object konstruktori argumentlarni e’tiborsiz qoldiradi, u har doim bo’sh obyektni yaratadi – bu bizda user2 da mavjud.

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…)