Prototiplar, meros

Prototip metodlari, __proto__siz obyektlar

__proto__ โ€” [[Prototype]] ni o'rnatish va o'qishning eng eski usuli, lekin u eskirgan (deprecated) hisoblanadi. Zamonaviy JavaScript prototiplar bilan ishlash uchun boshqa, ishonchliroq metodlarni taklif etadi. Bu darsda o'sha metodlar bilan tanishamiz.

Zamonaviy metodlar

Prototiplar bilan ishlashning uchta asosiy zamonaviy usuli bor:

methods-basic.js
// natija shu yerda chiqadi
Bu uch metod aynan bir vazifani __proto__ orqasidagi [[Prototype]] bilan bajaradi, lekin ishonchliroq va standart usulda. Zamonaviy kodda aynan shulardan foydalaning.

Object.create bilan deskriptorlar

Object.create ning ikkinchi argumenti ixtiyoriy โ€” u xossa deskriptorlarini beradi. Bu bir chaqiruvda ham prototip, ham xossalarni o'rnatishga imkon beradi:

methods-descriptors.js
// natija shu yerda chiqadi

Object.create obyektni yuzaki (shallow) nusxalash uchun ham qulay โ€” u barcha xossalarni, jumladan getter/setter'larni va to'g'ri prototipni saqlab, aniq nusxa yaratadi:

methods-clone.js
// natija shu yerda chiqadi

Nima uchun __proto__ eskirgan?

__proto__ texnik jihatdan tilning yadrosida emas, brauzerlar uchun qo'shimcha standart (Annex B) sifatida ta'riflangan. Undan qochishning bir necha sabablari bor:

Agar kalitlar tashqi (foydalanuvchi) manbadan kelsa, __proto__ maxsus kalit sifatida g'alati xatti-harakat qilishi mumkin. Masalan, foydalanuvchi __proto__ nomli "kalit" kiritsa, oddiy tayinlash prototipni buzishga urinadi. Buni quyida ko'ramiz.
methods-proto-bug.js
// natija shu yerda chiqadi

Ko'rib turganingizdek, __proto__ kaliti oddiy ma'lumot kaliti kabi ishlamaydi โ€” u prototipni o'zgartirishga urinadi. Bu obyektni oddiy lug'at (map) sifatida ishlatganda jiddiy xatolarga olib keladi.

Object.create(null) โ€” "toza" obyekt

Yuqoridagi muammoning yechimi โ€” prototipi umuman yo'q obyekt yaratish. Object.create(null) prototipi null bo'lgan "toza" (chinakam bo'sh) obyekt yasaydi. Bunday obyektda __proto__ maxsus getter/setter'i yo'q, shuning uchun u oddiy kalit sifatida ishlaydi:

methods-clean.js
// natija shu yerda chiqadi

Bunday obyektlar ba'zan "very plain" yoki "pure dictionary" (toza lug'at) deb ataladi, chunki ular oddiy obyektlardan ham soddaroq โ€” ularda umuman meros olingan xossa yo'q.

Toza obyektning bir kamchiligi bor: u Object.prototype dan meros olmagani uchun tayyor metodlarga (masalan, toString, hasOwnProperty) ega emas. Ammo Object.keys, Object.values kabi Object.* metodlari baribir ishlaydi, chunki ular obyektning o'zida emas, Object konstruktorida joylashgan.
methods-clean-methods.js
// natija shu yerda chiqadi
Foydalanuvchidan kelgan kalitlar bilan lug'at (dictionary) tuzayotganingizda Object.create(null) yoki Map dan foydalaning. Ular __proto__ kabi maxsus kalitlar keltirib chiqaradigan xavfsizlik va mantiq muammolaridan xoli bo'ladi.

Barcha xossalarni olish metodlari

Obyekt xossalarini olishning turli metodlari mavjud. Ularning barchasi obyektning O'Z xossalari ustida ishlaydi (prototipdagilar hisobga olinmaydi):

methods-keys.js
// natija shu yerda chiqadi

Xulosa