Noyob va shaxsiy obyekt xususiyatlarini yaratish, kodni qo'llab-quvvatlashni yaxshilash va nomlar to'qnashuvining oldini olish uchun kuchli vosita bo'lgan JavaScript Symbol'larini o'rganing. Amaliy misollar bilan tanishing.
JavaScript Symbol'lari: Noyob Xususiyat Kalitlarini Mukammal Boshqarish
O'zining moslashuvchanligi va dinamik tabiati bilan tanilgan JavaScript tili obyekt xususiyatlarini boshqarish uchun turli xil imkoniyatlarni taqdim etadi. Ular orasida Symbol'lar noyob va ko'pincha shaxsiy xususiyat kalitlarini yaratish uchun kuchli vosita sifatida ajralib turadi. Ushbu maqola JavaScript loyihalaringizda Symbol'larni tushunish va ulardan samarali foydalanish bo'yicha to'liq qo'llanma bo'lib, ularning asoslari, amaliy qo'llanilishi va ilg'or foydalanish holatlarini o'z ichiga oladi.
JavaScript Symbol'lari nima?
ECMAScript 2015 (ES6) da taqdim etilgan Symbol'lar sonlar, satrlar va mantiqiy qiymatlar kabi primitiv ma'lumotlar turidir. Biroq, boshqa primitivlardan farqli o'laroq, har bir Symbol nusxasi noyob va o'zgarmasdir. Bu noyoblik ularni mavjud yoki kelajakdagi xususiyatlar bilan to'qnashmasligi kafolatlangan obyekt xususiyatlarini yaratish uchun ideal qiladi. Ularni JavaScript kodingiz ichidagi ichki identifikatorlar deb o'ylang.
Symbol Symbol()
funksiyasi yordamida yaratiladi. Qo'shimcha ravishda, tuzatish (debugging) maqsadlarida tavsif sifatida satr berishingiz mumkin, ammo bu tavsif Symbol'ning noyobligiga ta'sir qilmaydi.
Symbol'ning Asosiy Yaratilishi
Quyida Symbol yaratishning oddiy misoli keltirilgan:
const mySymbol = Symbol("description");
console.log(mySymbol); // Natija: Symbol(description)
Muhimi, agar ikkita Symbol bir xil tavsif bilan yaratilgan bo'lsa ham, ular baribir bir-biridan farq qiladi:
const symbol1 = Symbol("same description");
const symbol2 = Symbol("same description");
console.log(symbol1 === symbol2); // Natija: false
Nima uchun Symbol'lardan foydalanish kerak?
Symbol'lar JavaScript dasturlashda bir nechta umumiy muammolarni hal qiladi:
- Nomlar to'qnashuvining oldini olish: Katta loyihalar yoki uchinchi tomon kutubxonalari bilan ishlaganda, nomlar to'qnashuvi jiddiy muammo bo'lishi mumkin. Symbol'larni xususiyat kalitlari sifatida ishlatish sizning xususiyatlaringiz mavjud xususiyatlarni tasodifan qayta yozib yubormasligini ta'minlaydi. Tasavvur qiling, siz Tokiodagi dasturchi tomonidan yaratilgan kutubxonani kengaytirmoqdasiz va o'sha kutubxona tomonidan boshqariladigan obyektga yangi xususiyat qo'shmoqchisiz. Symbol'dan foydalanish ularning allaqachon belgilagan xususiyatini tasodifan bekor qilishning oldini oladi.
- Shaxsiy xususiyatlar yaratish: JavaScript'da boshqa ba'zi tillardagidek haqiqiy shaxsiy (private) a'zolar mavjud emas. Pastki chiziq prefiksidan (
_myProperty
) foydalanish kabi shartli belgilar mavjud bo'lsa-da, ular kirishni cheklamaydi. Symbol'lar esa inkapsulyatsiyaning kuchliroq shaklini ta'minlaydi. Garchi to'liq himoyalanmagan bo'lsa-da, ular xususiyatlarga obyekt tashqarisidan kirishni ancha qiyinlashtiradi, bu esa kodning yaxshiroq tuzilishi va qo'llab-quvvatlanishiga yordam beradi. - Metaprogrammalash: Symbol'lar metaprogrammalashda o'rnatilgan JavaScript operatsiyalari uchun maxsus xatti-harakatlarni belgilash uchun ishlatiladi. Bu sizga obyektlarning iteratsiya yoki turini o'zgartirish kabi til xususiyatlari bilan qanday o'zaro ta'sir qilishini sozlash imkonini beradi.
Symbol'larni Obyekt Xususiyat Kalitlari Sifatida Ishlatish
Symbol'ni xususiyat kaliti sifatida ishlatish uchun uni to'rtburchak qavslarga oling:
const mySymbol = Symbol("myProperty");
const myObject = {
[mySymbol]: "Hello, Symbol!"
};
console.log(myObject[mySymbol]); // Natija: Hello, Symbol!
Xususiyatga nuqta belgisi (myObject.mySymbol
) yordamida to'g'ridan-to'g'ri kirishish ishlamaydi. Siz Symbol'ning o'zi bilan qavs belgisidan foydalanishingiz kerak.
Misol: Nomlar To'qnashuvining Oldini Olish
Tasavvur qiling, siz `status` nomli xususiyatdan foydalanadigan uchinchi tomon kutubxonasini kengaytirmoqdasiz:
// Uchinchi tomon kutubxonasi
const libraryObject = {
status: "ready",
processData: function() {
console.log("Processing...");
}
};
// Sizning kodingiz (kutubxonani kengaytirish)
libraryObject.status = "pending"; // Potentsial to'qnashuv!
console.log(libraryObject.status); // Natija: pending (qayta yozilgan!)
Symbol'dan foydalanib, bu to'qnashuvdan qochishingiz mumkin:
const libraryObject = {
status: "ready",
processData: function() {
console.log("Processing...");
}
};
const myStatusSymbol = Symbol("myStatus");
libraryObject[myStatusSymbol] = "pending";
console.log(libraryObject.status); // Natija: ready (asl qiymat)
console.log(libraryObject[myStatusSymbol]); // Natija: pending (sizning qiymatingiz)
Misol: Yarim-Shaxsiy Xususiyatlar Yaratish
Symbol'lardan obyekt tashqarisidan kirish qiyinroq bo'lgan xususiyatlarni yaratish uchun foydalanish mumkin. Garchi qat'iy shaxsiy bo'lmasa-da, ular ma'lum darajada inkapsulyatsiyani ta'minlaydi.
class MyClass {
#privateField = 'Bu haqiqiy shaxsiy maydon (ES2022)'; // Yangi shaxsiy sinf xususiyati
constructor(initialValue) {
this.publicProperty = initialValue;
this.privateSymbol = Symbol("privateValue");
this[this.privateSymbol] = "Secret!";
}
getPrivateValue() {
return this[this.privateSymbol];
}
}
const myInstance = new MyClass("Initial Value");
console.log(myInstance.publicProperty); // Natija: Initial Value
//console.log(myInstance.privateSymbol); // Natija: undefined (Symbol'ga to'g'ridan-to'g'ri kirib bo'lmaydi)
//console.log(myInstance[myInstance.privateSymbol]); // Sinf ichida ishlaydi
//console.log(myInstance.#privateField); // Natija: Sinfdan tashqarida xatolik
console.log(myInstance.getPrivateValue());//maxfiy
Agar Symbol'ni bilsangiz, Symbol xususiyatiga kirish hali ham mumkin bo'lsa-da, bu tasodifiy yoki kutilmagan kirish ehtimolini ancha kamaytiradi. Yangi JavaScript xususiyati "#" haqiqiy shaxsiy xususiyatlarni yaratadi.
Taniqli Symbol'lar
JavaScript taniqli symbol'lar (tizim symbol'lari deb ham ataladi) to'plamini belgilaydi. Bu symbol'lar oldindan belgilangan ma'nolarga ega va JavaScript'ning o'rnatilgan operatsiyalari xatti-harakatlarini sozlash uchun ishlatiladi. Ularga Symbol
obyektining statik xususiyatlari sifatida kiriladi (masalan, Symbol.iterator
).
Quyida eng ko'p ishlatiladigan taniqli symbol'lardan ba'zilari keltirilgan:
Symbol.iterator
: Obyekt uchun standart iteratorni belgilaydi. ObyektdaSymbol.iterator
metodi mavjud bo'lganda, u iterabll bo'ladi, ya'ni unifor...of
sikllari va spread operatori (...
) bilan ishlatish mumkin.Symbol.toStringTag
: Obyektning maxsus satr tavsifini belgilaydi. Bu obyektdaObject.prototype.toString()
chaqirilganda ishlatiladi.Symbol.hasInstance
: Obyekt konstruktor funksiyasining nusxasi (instance) hisoblanishini aniqlaydi.Symbol.toPrimitive
: Obyektni primitiv qiymatga (masalan, son yoki satr) o'zgartirish usulini belgilaydi.
Misol: Symbol.iterator
bilan Iteratsiyani Sozlash
Keling, satr belgilarini teskari tartibda takrorlaydigan iterabll obyekt yaratamiz:
const reverseString = {
text: "JavaScript",
[Symbol.iterator]: function* () {
for (let i = this.text.length - 1; i >= 0; i--) {
yield this.text[i];
}
}
};
for (const char of reverseString) {
console.log(char); // Natija: t, p, i, r, c, S, a, v, a, J
}
console.log([...reverseString]); //Natija: ["t", "p", "i", "r", "c", "S", "a", "v", "a", "J"]
Ushbu misolda biz Symbol.iterator
ga tayinlangan generator funksiyasini aniqlaymiz. Bu funksiya satrning har bir belgisini teskari tartibda qaytaradi va reverseString
obyektini iterabll qiladi.
Misol: Symbol.toPrimitive
bilan Turni O'zgartirishni Sozlash
Symbol.toPrimitive
metodini belgilash orqali obyektning primitiv qiymatga (masalan, matematik amallarda yoki satrlarni birlashtirishda ishlatilganda) qanday o'zgartirilishini nazorat qilishingiz mumkin.
const myObject = {
value: 42,
[Symbol.toPrimitive](hint) {
if (hint === "number") {
return this.value;
}
if (hint === "string") {
return `The value is ${this.value}`;
}
return this.value;
}
};
console.log(Number(myObject)); // Natija: 42
console.log(String(myObject)); // Natija: The value is 42
console.log(myObject + 10); // Natija: 52 (songa o'zgartirish)
console.log("Value: " + myObject); // Natija: Value: The value is 42 (satrga o'zgartirish)
hint
argumenti amalga oshirilayotgan o'zgartirish turini ("number"
, "string"
, yoki "default"
) bildiradi. Bu sizga kontekstga qarab o'zgartirish xatti-harakatini sozlash imkonini beradi.
Symbol Registri
Symbol'lar odatda noyob bo'lsa-da, ba'zida ilovangizning turli qismlarida bir Symbol'ni ulashishni xohlashingiz mumkin. Symbol registri buning uchun mexanizmni taqdim etadi.
Symbol.for(key)
metodi global Symbol registridan Symbol yaratadi yoki oladi. Agar berilgan kalit bilan Symbol allaqachon mavjud bo'lsa, u o'sha Symbol'ni qaytaradi; aks holda, u yangi Symbol yaratadi va uni kalit bilan ro'yxatdan o'tkazadi.
const globalSymbol1 = Symbol.for("myGlobalSymbol");
const globalSymbol2 = Symbol.for("myGlobalSymbol");
console.log(globalSymbol1 === globalSymbol2); // Natija: true (bir xil Symbol)
console.log(Symbol.keyFor(globalSymbol1)); // Natija: myGlobalSymbol (kalitni olish)
Symbol.keyFor(symbol)
metodi global registrdagi Symbol bilan bog'langan kalitni oladi. Agar Symbol Symbol.for()
yordamida yaratilmagan bo'lsa, u undefined
qiymatini qaytaradi.
Symbol'lar va Obyektlarni Sanab Chiqish
Symbol'larning asosiy xususiyati shundaki, ular not enumerable by default. Bu ularning Object.keys()
, Object.getOwnPropertyNames()
va for...in
sikllari kabi metodlar tomonidan e'tiborsiz qoldirilishini anglatadi. Bu ularning "yashirin" yoki ichki xususiyatlarni yaratish uchun foydaliligini yanada oshiradi.
const mySymbol = Symbol("myProperty");
const myObject = {
name: "John Doe",
[mySymbol]: "Hidden Value"
};
console.log(Object.keys(myObject)); // Natija: ["name"]
console.log(Object.getOwnPropertyNames(myObject)); // Natija: ["name"]
for (const key in myObject) {
console.log(key); // Natija: name
}
Symbol xususiyatlarini olish uchun siz Object.getOwnPropertySymbols()
dan foydalanishingiz kerak:
const mySymbol = Symbol("myProperty");
const myObject = {
name: "John Doe",
[mySymbol]: "Hidden Value"
};
console.log(Object.getOwnPropertySymbols(myObject)); // Natija: [Symbol(myProperty)]
Brauzer Muvofiqligi va Transpilyatsiya
Symbol'lar barcha zamonaviy brauzerlar va Node.js versiyalarida qo'llab-quvvatlanadi. Biroq, agar siz eski brauzerlarni qo'llab-quvvatlashingiz kerak bo'lsa, kodingizni JavaScript'ning mos keluvchi versiyasiga o'zgartirish uchun Babel kabi transpilyatordan foydalanishingiz kerak bo'lishi mumkin.
Symbol'lardan Foydalanish bo'yicha Eng Yaxshi Amaliyotlar
- Ayniqsa, tashqi kutubxonalar yoki katta kod bazalari bilan ishlaganda nomlar to'qnashuvining oldini olish uchun Symbol'lardan foydalaning. Bu, ayniqsa, bir nechta dasturchilar bir xil kod ustida ishlayotgan hamkorlikdagi loyihalarda muhimdir.
- Yarim shaxsiy xususiyatlarni yaratish va kod inkapsulyatsiyasini yaxshilash uchun Symbol'lardan foydalaning. Haqiqiy shaxsiy a'zolar bo'lmasa-da, ular tasodifiy kirishdan sezilarli darajada himoya qiladi. Agar sizning ish muhitingiz qo'llab-quvvatlasa, qat'iyroq maxfiylik uchun shaxsiy sinf xususiyatlaridan foydalanishni o'ylab ko'ring.
- O'rnatilgan JavaScript operatsiyalari va metaprogrammalash xatti-harakatlarini sozlash uchun taniqli symbol'lardan foydalaning. Bu sizga yanada ifodali va moslashuvchan kod yaratishga imkon beradi.
- Symbol registridan (
Symbol.for()
) faqat ilovangizning turli qismlarida Symbol'ni ulashishingiz kerak bo'lgandagina foydalaning. Ko'p hollarda,Symbol()
bilan yaratilgan noyob Symbol'lar yetarli bo'ladi. - Symbol'lardan foydalanishingizni kodingizda aniq hujjatlashtiring. Bu boshqa dasturchilarga ushbu xususiyatlarning maqsadi va niyatini tushunishga yordam beradi.
Ilg'or Foydalanish Holatlari
- Freymvorklarni ishlab chiqish: Symbol'lar freymvorklarni ishlab chiqishda foydalanuvchi tomonidan belgilangan xususiyatlarga aralashmasdan ichki holatlarni, hayotiy sikl hook'larini va kengaytirish nuqtalarini aniqlash uchun juda foydalidir.
- Plagin tizimlari: Plagin arxitekturasida Symbol'lar plaginlarga nomlar to'qnashuvi xavfisiz asosiy obyektlarni kengaytirishning xavfsiz usulini taqdim etishi mumkin. Har bir plagin o'zining maxsus xususiyatlari va metodlari uchun o'z Symbol'lar to'plamini belgilashi mumkin.
- Metama'lumotlarni saqlash: Symbol'lar obyektlarga metama'lumotlarni aralashmagan holda biriktirish uchun ishlatilishi mumkin. Bu obyektni keraksiz xususiyatlar bilan to'ldirmasdan, ma'lum bir kontekstga tegishli ma'lumotlarni saqlash uchun foydalidir.
Xulosa
JavaScript Symbol'lari obyekt xususiyatlarini boshqarish uchun kuchli va ko'p qirrali mexanizmni taqdim etadi. Ularning noyobligi, sanab chiqilmasligi va taniqli symbol'lar bilan aloqasini tushunib, siz yanada mustahkam, qo'llab-quvvatlanadigan va ifodali kod yozishingiz mumkin. Kichik shaxsiy loyiha yoki yirik korporativ ilova ustida ishlayapsizmi, Symbol'lar sizga nomlar to'qnashuvidan qochishga, yarim shaxsiy xususiyatlarni yaratishga va o'rnatilgan JavaScript operatsiyalarining xatti-harakatlarini sozlashga yordam beradi. JavaScript mahoratingizni oshirish va yaxshiroq kod yozish uchun Symbol'larni o'zlashtiring.