Xossa bayroqlari va deskriptorlari
Biz obyekt xossalarini oddiy "kalit: qiymat" juftliklari deb bilamiz. Aslida esa xossa โ bu ancha moslashuvchan va boshqariladigan narsa. Ushbu darsda xossalarning yashirin bayroqlari (flags) bilan tanishamiz va ularni deskriptorlar orqali qanday sozlashni o'rganamiz.
Xossa bayroqlari nima?
Obyekt xossalari qiymatdan tashqari yana uchta maxsus atribut โ bayroq (flag)ga ega. Ular true yoki false qiymat oladi:
- writable โ agar
truebo'lsa, xossa qiymatini o'zgartirish mumkin; aks holda u faqat o'qish uchun (read-only) bo'ladi; - enumerable โ agar
truebo'lsa, xossa sikllarda (masalan,for..in) sanab o'tiladi; aks holda "yashirin" bo'ladi; - configurable โ agar
truebo'lsa, xossani o'chirish va uning bayroqlarini o'zgartirish mumkin; aks holda bu taqiqlanadi.
Biz xossani odatdagidek yaratganimizda, bu uchala bayroq avtomatik ravishda true qiymatini oladi. Shuning uchun biz ularni odatda sezmaymiz โ hamma narsa "erkin" ishlaydi.
Object.getOwnPropertyDescriptor
Xossa haqidagi to'liq ma'lumotni โ qiymati va barcha bayroqlarini โ bilish uchun Object.getOwnPropertyDescriptor metodidan foydalanamiz. Sintaksisi quyidagicha:
let descriptor = Object.getOwnPropertyDescriptor(obj, propertyName);
objโ ma'lumot olinadigan obyekt;propertyNameโ xossa nomi (satr ko'rinishida).
Natijada "xossa deskriptori" (property descriptor) deb ataladigan obyekt qaytadi. U qiymatni va barcha bayroqlarni saqlaydi. Quyidagi misolni ishga tushiring:
Ko'rib turganingizdek, oddiy usulda yaratilgan xossada value, writable, enumerable va configurablening hammasi truega teng.
Object.defineProperty
Bayroqlarni o'zgartirish uchun Object.defineProperty metodidan foydalanamiz:
Object.defineProperty(obj, propertyName, descriptor);
obj,propertyNameโ obyekt va xossa nomi;descriptorโ qo'llaniladigan deskriptor obyekti.
Agar bunday nomli xossa mavjud bo'lsa, defineProperty uning bayroqlarini yangilaydi. Aks holda esa berilgan qiymat va bayroqlar bilan yangi xossa yaratadi; bunda ko'rsatilmagan bayroq false deb qabul qilinadi.
defineProperty orqali yaratildi, lekin bayroqlar aniq ko'rsatilmadi. Shuning uchun writable, enumerable va configurable avtomatik false bo'lib qoladi โ bu oddiy user.name = "Jasur"dan tubdan farq qiladi!writable โ faqat o'qish uchun xossa
name xossasini faqat o'qish uchun (read-only) qilib qo'yamiz. Buning uchun writableni falsega o'zgartiramiz. Endi hech kim uning qiymatini o'zgartira olmaydi:
"use strict" yozilgan qat'iy rejimda esa bu urinish xatolik (TypeError) chaqiradi.Faqat o'qish uchun xossani o'zgartirishga urinish qat'iy rejimda qanday xato berishini ko'rsatuvchi misol:
enumerable โ sanashdan yashirish
Endi obyektga maxsus toString metodini qo'shamiz. Odatda obyektlardagi barcha xossalar for..in siklida ko'rinadi, bu esa har doim ham kerak emas. enumerable: false qilib, xossani sikllardan va Object.keysdan yashiramiz:
Object.keys(), Object.values() va for..in natijasidan tushib qoladi, lekin ular baribir mavjud โ ularga to'g'ridan-to'g'ri (user.toString) murojaat qilsa bo'ladi.configurable โ o'zgarmas xossa
configurable: false bayrog'i ba'zi muhim ichki xossalarga o'rnatilgan bo'ladi. Bunday xossani delete orqali o'chirib bo'lmaydi va uning bayroqlarini defineProperty orqali o'zgartirib ham bo'lmaydi.
Masalan, Math.PI faqat o'qiladigan, sanalmaydigan va sozlanmaydigan (non-configurable) xossadir. Buni tekshiramiz:
Xossani "abadiy muhrlash" uchun uni bir vaqtda writable: false va configurable: false qilib qo'yish odatiy usuldir. Shundan so'ng qiymatni ham, bayroqlarni ham hech kim o'zgartira olmaydi:
configurable: false โ bu bir tomonlama harakat. Xossani sozlanmas qilib qo'ygandan so'ng, uni defineProperty orqali qaytadan sozlanadigan (configurable: true) qilib bo'lmaydi. Bu qaytmas amaldir.configurable false, lekin writable true bo'lsa, qiymatni hali ham o'zgartirish mumkin, shuningdek writableni truedan falsega o'zgartirish ham ruxsat etiladi (aksincha emas).Object.defineProperties
Bir vaqtning o'zida bir nechta xossani e'lon qilish uchun Object.defineProperties qulay:
Object.defineProperties(obj, {
prop1: descriptor1,
prop2: descriptor2
// ...
});
Object.getOwnPropertyDescriptors
Barcha xossalarning deskriptorlarini bir vaqtda olish uchun Object.getOwnPropertyDescriptors(obj) ishlatiladi. U Object.defineProperties bilan birga obyektni bayroqlari bilan birga nusxalash uchun juda foydali:
let clone = Object.defineProperties({}, Object.getOwnPropertyDescriptors(obj));
Odatdagi for..in yoki Object.assign nusxalashi bayroqlarni ko'chirmaydi va sanalmaydigan (non-enumerable) xossalarni tashlab ketadi. Yuqoridagi usul esa xossani to'liq, barcha bayroqlari bilan ko'chiradi:
Butun obyektni himoyalash
Yuqoridagi metodlar bitta xossaga ta'sir qiladi. Butun obyektni cheklovchi uchta "global" metod ham bor:
- Object.preventExtensions(obj) โ obyektga yangi xossa qo'shishni taqiqlaydi (mavjudlarini o'zgartirsa bo'ladi);
- Object.seal(obj) โ yangi xossa qo'shishni taqiqlaydi va barcha mavjud xossalarni
configurable: falseqiladi (qiymatni o'zgartirish mumkin, lekin o'chirib bo'lmaydi); - Object.freeze(obj) โ eng qattiq: yangi xossa qo'shish, o'chirish va qiymatlarni o'zgartirishni ham taqiqlaydi (barcha xossalarni
configurable: falsevawritable: falseqiladi).
Ular uchun mos tekshiruv metodlari mavjud: Object.isExtensible(obj), Object.isSealed(obj) va Object.isFrozen(obj).
Xulosa
- Har bir ma'lumot xossasi qiymatdan tashqari uchta bayroqqa ega: writable, enumerable, configurable;
- Oddiy usulda yaratilganda ularning hammasi
truebo'ladi; Object.getOwnPropertyDescriptor(obj, prop)โ bitta xossa deskriptorini o'qiydi;Object.defineProperty(obj, prop, descriptor)โ xossa va uning bayroqlarini o'rnatadi (ko'rsatilmagan bayroqfalse);Object.definePropertiesvaObject.getOwnPropertyDescriptorsโ ko'p xossa bilan ishlaydi va to'liq nusxalash uchun ideal;Object.preventExtensions / seal / freezeโ butun obyektni turli darajada himoyalaydi.