Mundarija (32)
- Bu darsda
- 1. Nega bu kerak?
- 2. Symbol yaratish
- 2.1 Har safar yangi
- 2.2 Tavsif — faqat eslatma
- 2.3 new siz
- 2.4 Satrga o'zi aylanmaydi
- 3. Symbol — obyekt kaliti
- 3.1 Yozish va o'qish
- 3.2 Qayerda ko'rinadi, qayerda yo'q
- 3.3 Nega bu foydali
- 3.4 Klassda symbol nomli metod
- 3.5 Symbol — Map va Set da
- 4. Yashirin, lekin private emas
- 5. Global registr: Symbol.for
- 5.1 Bitta symbol — ko'p joyda
- 5.2 Registrning narxi
- 6. Symbol amaliyotda
- 7. Ko'p uchraydigan xatolar
- 7.1 Symbol'ni satrga qo'shish
- 7.2 Symbol kalitni nuqta bilan o'qish
- 7.3 Ikki marta Symbol("...") va bir xil kutish
- 7.4 Symbol kalitni JSON'da kutish
- 7.5 new Symbol()
- 8. Mashqlar
- 1-mashq (oson): Tavsifli symbol
- 2-mashq (o'rta): To'qnashmaydigan belgilar
- 3-mashq (qiyin): Buyurtma holatlari
- 4-mashq: Vazifalar qadami — tanlangan vazifalar belgisi (mashqlar repo)
- 9. Real ishda
- Xulosa
- Manbalar
JavaScript Symbol: hech qachon to'qnashmaydigan noyob kalit
Qisqacha:
Symbol— har safar yangi, boshqa hech bir qiymatga teng bo'lmaydigan primitiv.Symbol("id") === Symbol("id")—false. U asosan obyekt kaliti sifatida ishlatiladi: bunday kalit boshqa kodning xususiyatlari bilan to'qnashmaydi vaObject.keys,for...in,JSON.stringifyda ko'rinmaydi. Bir xil symbol'ni turli joyda olish kerak bo'lsa —Symbol.for("nom").
Bu darsda
- Symbol yaratib, uning tavsifini o'qiy olasiz va nega u noyob ekanini tushuntira olasiz.
- Symbol'ni obyekt kaliti qila olasiz va u qaysi amallarda ko'rinishini, qaysilarida ko'rinmasligini bilasiz.
Symbol.forvaSymbol.keyForbilan global registrdan foydalana olasiz.- Symbol "yashirin", lekin private emasligini va
#maydondan farqini tushuntira olasiz. - Symbol bilan bog'liq ikki
TypeErrorni tanib, tuzata olasiz.
Oldin bilishingiz kerak: Ma'lumot turlari xaritasi, Shorthand, computed kalitlar va metodlar, Obyekt bo'ylab yurish, Map, WeakMap va WeakRef.
1. Nega bu kerak?
Ma'lumot turlari xaritasi darsida yettinchi primitiv turni bir gap bilan tanishtirgan edik: symbol. O'shanda "boshlang'ich bosqichda deyarli uchratmaysiz" degan edik. Endi u nima uchun yaratilganini ko'ramiz.
Tasavvur qiling: «Bahor» saytida buyurtma obyektlari bor. Ikki xil kod ularga o'z belgisini qo'shmoqchi. Birinchisi — statistika moduli: buyurtmani "hisoblandi" deb belgilaydi. Ikkinchisi — boshqa dasturchi yozgan yetkazib berish moduli. Ikkalasi ham bir xil nom tanladi:
const buyurtma = { id: 17, taom: "osh" };
// statistika moduli
buyurtma.belgi = "hisoblandi";
// yetkazib berish moduli — boshqa odam yozgan
buyurtma.belgi = "yo'lda";
console.log(buyurtma.belgi); // yo'ldaIkkinchi modul birinchisining belgisini o'chirib yubordi — xatosiz. Statistika endi buyurtmani hisoblanmagan deb o'ylaydi va ikkinchi marta sanaydi. Nomlar oddiy satr bo'lgani uchun to'qnashdi.
WeakMap darsida bu muammoning bitta yechimini ko'rdik: ma'lumotni obyektdan tashqarida saqlash. Symbol — ikkinchi yechim: ma'lumot obyektning o'zida, lekin kaliti hech kim takrorlay olmaydigan nom. Hayotdan o'xshatish: bir xil ko'rinishdagi ikki kalit emas, har biri uchun noyob kesilgan kalit. Ikkala qulf eshikda yonma-yon turadi, lekin har biri faqat o'z kalitiga ochiladi.
2. Symbol yaratish
2.1 Har safar yangi
Symbol — har chaqirilganda mutlaqo yangi qiymat yaratadigan primitiv tur. U Symbol() funksiyasi bilan yaratiladi:
const a = Symbol("belgi");
const b = Symbol("belgi");
console.log(a === b); // false
console.log(a === a); // true
console.log(typeof a); // symbola va b bir xil tavsif bilan yaratildi, lekin teng emas. Har Symbol(...) chaqiruvi — yangi, dunyoda yagona qiymat. Uni faqat o'zi bilan solishtirsangiz true chiqadi.
Bu boshqa primitivlardan keskin farq. "osh" === "osh" — true, chunki satr ichidagi harflar bo'yicha solishtiriladi. Symbol'ning esa "ichi" yo'q — u faqat o'zi.
2.2 Tavsif — faqat eslatma
Qavs ichidagi satr — tavsif (description). U symbol'ning ma'nosiga ta'sir qilmaydi, faqat dasturchiga — konsolda va xato topishda — yordam beradi:
const belgi = Symbol("statistika belgisi");
console.log(belgi); // Symbol(statistika belgisi)
console.log(belgi.description); // statistika belgisi
console.log(belgi.toString()); // Symbol(statistika belgisi)
console.log(Symbol().description); // undefineddescription — tavsifning o'zi, toString() — Symbol(...) ko'rinishidagi satr. Tavsifsiz symbol ham yaratish mumkin, lekin konsolda Symbol() dan boshqa narsa ko'rmaysiz — doim tavsif yozing.
2.3 new siz
const belgi = new Symbol("belgi");TypeError: Symbol is not a constructorTarjimasi: "Symbol — konstruktor emas". O'rnatilgan prototiplar darsida ko'rgan edik: BigInt kabi yangi primitivlar o'rami new bilan yaratilmaydi. Symbol ham primitiv — uni oddiy funksiya kabi chaqiring.
2.4 Satrga o'zi aylanmaydi
Yashirin coercion darsida JavaScript qiymatlarni o'zi satrga va songa aylantirishini ko'rdik. Symbol bunga yo'l qo'ymaydi:
const belgi = Symbol("belgi");
console.log(`Kalit: ${belgi}`);TypeError: Cannot convert a Symbol value to a stringTarjimasi: "Symbol qiymatini satrga aylantirib bo'lmaydi". belgi + "" ham xuddi shu xatoni beradi, +belgi esa Cannot convert a Symbol value to a number. Nega bunday qattiq? Agar symbol jimgina "Symbol(belgi)" satriga aylansa, uni kalit qilib yozganda oddiy satr kalit paydo bo'lardi. Noyoblik yo'qolardi. Til buni ataylab taqiqlagan.
Aniq aylantirish esa ishlaydi:
const belgi = Symbol("belgi");
console.log(`Kalit: ${belgi.description}`); // Kalit: belgi
console.log(String(belgi)); // Symbol(belgi)
console.log(Boolean(belgi)); // trueString(...) — aniq so'rov, u ruxsat etilgan. Mantiqiy qiymatga esa doim true bo'ladi — symbol "truthy".
Tekshirib ko'ring:
Symbol("x").description === Symbol("x").descriptionnima beradi?
Javob
true. Bu yerda symbol'lar emas, ularning tavsiflari — oddiy "x" satrlari solishtirilyapti. Symbol'larning o'zi teng emas (Symbol("x") === Symbol("x") — false), lekin tavsifi bir xil bo'lishi mumkin.
3. Symbol — obyekt kaliti
3.1 Yozish va o'qish
Obyekt kaliti doim satr bo'ladi, deb Obyekt: kalit-qiymat juftliklari darsida aytgan edik — "yagona istisno — symbol". Symbol kalit computed kalit — kvadrat qavs — bilan yoziladi va o'qiladi:
const hisoblandi = Symbol("hisoblandi");
const yolda = Symbol("yolda");
const buyurtma = { id: 17, taom: "osh" };
buyurtma[hisoblandi] = true;
buyurtma[yolda] = true;
console.log(buyurtma[hisoblandi]);
console.log(buyurtma);Konsolda:
true
{ id: 17, taom: 'osh', Symbol(hisoblandi): true, Symbol(yolda): true }Ikki modul endi to'qnashmaydi: har biri o'z symbol'iga yozdi. Hatto ikkalasi ham Symbol("belgi") deb yaratganda ham — baribir ikki xil kalit bo'lardi.
Obyekt literali ichida ham yozish mumkin: { taom: "osh", [hisoblandi]: true }.
Nuqta bilan o'qib bo'lmaydi: buyurtma.hisoblandi — bu "hisoblandi" degan satr kalitni qidiradi, u yo'q, undefined chiqadi. Symbol kalit — faqat [o'zgaruvchi] bilan.
3.2 Qayerda ko'rinadi, qayerda yo'q
Symbol kalitning eng muhim xususiyati — u oddiy "kalitlar ro'yxati" amallarida ko'rinmaydi:
const hisoblandi = Symbol("hisoblandi");
const buyurtma = { id: 17, taom: "osh", [hisoblandi]: true };
console.log(Object.keys(buyurtma));
console.log(JSON.stringify(buyurtma));
for (const kalit in buyurtma) {
console.log(kalit);
}
console.log(Object.getOwnPropertySymbols(buyurtma));
console.log(hisoblandi in buyurtma);Konsolda:
[ 'id', 'taom' ]
{"id":17,"taom":"osh"}
id
taom
[ Symbol(hisoblandi) ]
trueObject.keys, JSON va for...in — uchalasi ham symbol'ni o'tkazib yubordi. Faqat maxsus Object.getOwnPropertySymbols uni ko'rdi.
Sxemada qaysi amal symbol kalitni ko'rishini bir qarashda solishtiring — chap guruh symbol'ni ko'rmaydi, o'ng guruh ko'radi:
flowchart TD
O["{ id, taom, [belgi] }"]
O --> K["Faqat satr kalitlar"]
O --> S["Symbol ham"]
K --> K1["Object.keys / values / entries"]
K --> K2["for...in"]
K --> K3["JSON.stringify"]
S --> S1["Object.getOwnPropertySymbols"]
S --> S2["Reflect.ownKeys"]
S --> S3["spread { ...obj }, Object.assign"]
S --> S4["obj[belgi], belgi in obj"]Reflect.ownKeys — satr va symbol kalitlarning hammasini beradigan metod; uni Proxy va Reflect darsida o'rganamiz, hozir bilish shart emas.
Spread bilan nusxalash symbol kalitlarni ham ko'chiradi. structuredClone esa ularni tashlab yuboradi:
const belgi = Symbol("belgi");
const asl = { taom: "osh", [belgi]: 1 };
console.log({ ...asl }[belgi]); // 1
console.log(structuredClone(asl)[belgi]); // undefinedBu farqni Sayoz va chuqur nusxalash darsidagi qoidaga qo'shib qo'ying.
3.3 Nega bu foydali
Ko'rinmaslik — symbol kalitning asosiy foydasi:
- Eksport toza qoladi.
JSON.stringifysymbol kalitni yozmaydi. Ichki belgi serverga yoki faylga tushib qolmaydi. - Boshqa kodni buzmaydi. Obyektni
Object.keysbilan aylanayotgan begona kod yangi kalitni ko'rmaydi va undan "hayron bo'lmaydi". - To'qnashuv yo'q. Kalitni faqat symbol'ning o'zi qo'lida bo'lgan kod o'qiy oladi.
Tekshirib ko'ring:
const s = Symbol("x"); const o = { [s]: 1, x: 2 };—Object.keys(o).lengthvao.xnimaga teng?
Javob
1 va 2. Object.keys faqat satr kalit "x" ni ko'radi. o.x ham satr kalitni o'qiydi — symbol s ning tavsifi "x" bo'lgani ahamiyatsiz. Symbol qiymatini faqat o[s] beradi.
3.4 Klassda symbol nomli metod
Symbol faqat ma'lumot emas, metod nomi ham bo'la oladi. Class maydonlari darsida klass ichidagi nom kvadrat qavsda hisoblanishi mumkinligini ko'rgan edik. Symbol bilan:
const chekYoz = Symbol("chekYoz");
class Buyurtma {
constructor(taom, narx) {
this.taom = taom;
this.narx = narx;
}
[chekYoz]() {
return `${this.taom} — ${this.narx} so'm`;
}
}
const b = new Buyurtma("Osh", 35000);
console.log(b[chekYoz]()); // Osh — 35000 so'm
console.log(Object.getOwnPropertyNames(Buyurtma.prototype));Konsolda:
Osh — 35000 so'm
[ 'constructor' ]Metod prototipda turibdi, lekin satr nomlar ro'yxatida yo'q — faqat constructor. Bu metodni faqat chekYoz symbol'ini bilgan kod chaqira oladi. Kimdir klassga tasodifan oddiy chekYoz nomli boshqa metod qo'shsa ham, ular to'qnashmaydi.
Aynan shu usul bilan JavaScript'ning o'zi ham obyektlarga "maxsus qobiliyat" beradi: Map, Set va massivning prototipida symbol nomli metodlar bor. Ularni keyingi darsda ochamiz.
3.5 Symbol — Map va Set da
Symbol oddiy primitiv qiymat, shuning uchun Map kaliti va Set qiymati ham bo'la oladi. Solishtirish o'sha-o'sha: faqat aynan o'sha symbol teng. new Set([Symbol("a"), Symbol("a")]).size — 2.
4. Yashirin, lekin private emas
Symbol kalitni "yashirin" deyish mumkin, lekin u private emas. Object.getOwnPropertySymbols bilan istalgan kod uni topadi va o'zgartiradi:
const balans = Symbol("balans");
const hamyon = { egasi: "Ali", [balans]: 50000 };
const [topildi] = Object.getOwnPropertySymbols(hamyon);
hamyon[topildi] = 0;
console.log(hamyon[balans]); // 0Uchta usulni solishtiramiz:
| Usul | Begona kod o'qiy oladimi? | Qachon |
|---|---|---|
| Symbol kalit | ha, maxsus metod bilan | to'qnashuvdan saqlash, "ichki" belgi |
# maydon (Private maydon) |
yo'q, umuman | o'z klassingizda haqiqiy private |
WeakMap (WeakMap) |
yo'q, WeakMap qo'lida bo'lmasa |
begona obyektga tashqi ma'lumot |
Qoida: himoya kerak bo'lsa — #. Faqat "nom to'qnashmasin, ro'yxatlarda ko'rinmasin" kerak bo'lsa — symbol.
5. Global registr: Symbol.for
5.1 Bitta symbol — ko'p joyda
Symbol("x") har safar yangisini yaratadi. Lekin ba'zan aksincha kerak: dasturning turli qismlari — turli fayllar, hatto turli oynalar (masalan, sahifa va uning ichidagi iframe) — bir xil symbol'ni olishi kerak. Buning uchun global symbol registri bor:
const a = Symbol.for("bahor.buyurtma");
const b = Symbol.for("bahor.buyurtma");
console.log(a === b); // true
console.log(Symbol.keyFor(a)); // bahor.buyurtma
console.log(Symbol.keyFor(Symbol("bahor.buyurtma"))); // undefinedSymbol.for(kalit) registrdan shu kalitli symbol'ni qidiradi. Bor bo'lsa — uni qaytaradi, yo'q bo'lsa — yaratib, registrga yozadi. Shuning uchun ikkinchi chaqiruv o'sha symbol'ni berdi. Symbol.keyFor — teskari amal: registrdagi symbol'ning kalitini aytadi. Oddiy Symbol() registrda yo'q — undefined.
Hayotdan o'xshatish: Symbol() — har mijozga yangi, takrorlanmas chek raqami. Symbol.for("...") — choyxonadagi stol raqami: "3-stol" deb kim aytsa ham, bitta stol tushuniladi.
5.2 Registrning narxi
Registrdagi symbol aslida noyoblikni yo'qotadi: kalit satrini bilgan har kim uni oladi. Shuning uchun kalitga "nomlar maydoni" qo'shiladi — "bahor.buyurtma", "kutubxona-nomi.belgi". Shunda boshqa kutubxona tasodifan bir xil nom tanlamaydi.
Yana bir farq: registrdagi symbol hech qachon "yo'qolmaydi" — har kim istalgan payt Symbol.for bilan qayta olishi mumkin. Shuning uchun u WeakMap kaliti bo'la olmaydi:
const kesh = new WeakMap();
kesh.set(Symbol.for("bahor.kesh"), 1);TypeError: Invalid value used as weak map keyOddiy Symbol("...") esa WeakMap kaliti bo'la oladi: undan nusxa yo'q, uni yo'qotsangiz — qayta tiklab bo'lmaydi. Bu imkoniyat yangi. Baseline ma'lumotiga ko'ra Firefox uni 146-versiyada qo'shgan (Chrome 109, Safari 16.4 da avvalroq bor edi). Shuning uchun 2025-yil 9-dekabrdan u Baseline'ning "yangi" (newly available) darajasida. Node 24 da ishlaydi — sinab ko'rdik.
Tekshirib ko'ring:
Symbol.for("a") === Symbol.for("a")vaSymbol("a") === Symbol.for("a")— nima beradi?
Javob
true va false. Birinchisida ikkala chaqiruv registrdan bitta symbol'ni oladi. Ikkinchisida Symbol("a") registrga umuman tegmaydi — u yangi, hech kimga teng bo'lmagan symbol yaratadi. Tavsiflari bir xil ("a") bo'lishi ahamiyatsiz.
6. Symbol amaliyotda
Kundalik ilova kodida siz symbol'ni kamdan-kam yaratasiz. U ko'proq ikki joyda uchraydi.
Kutubxonalar ichida. Kutubxona sizning obyektingizga o'z belgisini qo'yishi kerak bo'lsa, symbol ishlatadi — sizning kalitlaringizni buzmaslik uchun. Masalan, Immer kutubxonasi (ma'lumotning asl nusxasini buzmasdan o'zgartirishga yordam beradi; hozir bilish shart emas) o'zi yasagan qoralama obyektlarni Symbol.for("immer-state") kaliti bilan belgilaydi.
Noyob konstantalar. Qiymat faqat sizning kodingizdan kelishi kerak bo'lsa:
const KUTILMOQDA = Symbol("kutilmoqda");
const TAYYOR = Symbol("tayyor");
function holatMatni(holat) {
if (holat === KUTILMOQDA) return "Oshpaz tayyorlayapti";
if (holat === TAYYOR) return "Olib ketishingiz mumkin";
return "Noma'lum holat";
}
console.log(holatMatni(TAYYOR)); // Olib ketishingiz mumkin
console.log(holatMatni("tayyor")); // Noma'lum holatHolat satr bo'lganda, formadan yoki URL'dan kelgan istalgan "tayyor" satri haqiqiy holatdek o'tib ketardi. Symbol'ni esa tashqaridan "soxtalashtirib" bo'lmaydi — faqat TAYYOR o'zgaruvchisini qo'lida tutgan kod uni bera oladi.
Tilning o'zida. Eng muhimi: JavaScript'ning o'zi bir qator tayyor symbol'lardan foydalanadi. Set darsida new Set(5) xatosida Symbol(Symbol.iterator) degan g'alati nomni ko'rgan edingiz. Bu — "taniqli" symbol'lardan biri: for...of aynan shu kalitli metodni qidiradi. Ular keyingi darsning mavzusi.
Symbol tilga aynan shu sababdan qo'shilgan. 2015-yilda (ES2015) JavaScript'ga for...of kabi yangi imkoniyatlar kerak edi. Ular obyektda maxsus metodni qidirishi kerak edi. Agar bu metodning nomi oddiy satr bo'lganda — masalan, "iterator" — muammo chiqardi. Internetdagi millionlab eski saytlarda iterator nomli xususiyati bor obyektlar allaqachon bor edi. Yangi til qoidasi ularni boshqacha ishlatib, saytlarni buzib yuborardi.
Yechim — hech qachon to'qnashmaydigan nom. Eski kod symbol yarata olmagan, demak uning birorta kaliti yangi symbol bilan mos tushmaydi. Til eski dunyoni buzmasdan yangi "eshik" ochdi. Siz o'z kodingizda symbol'ni xuddi shu maqsadda ishlatasiz: boshqalarning obyektiga tegmasdan, o'z belgingizni qo'yish.
7. Ko'p uchraydigan xatolar
7.1 Symbol'ni satrga qo'shish
`${belgi}` yoki "Kalit: " + belgi — TypeError: Cannot convert a Symbol value to a string. Tuzatish: belgi.description yoki String(belgi).
7.2 Symbol kalitni nuqta bilan o'qish
buyurtma.hisoblandi — undefined, xatosiz. Tuzatish: buyurtma[hisoblandi] — o'zgaruvchi kvadrat qavsda.
7.3 Ikki marta Symbol("...") va bir xil kutish
Bir faylda Symbol("belgi") bilan yozib, boshqasida yana Symbol("belgi") bilan o'qish — undefined. Bu ikki xil symbol. Tuzatish: symbol'ni bir joyda yaratib, uni o'zgaruvchi orqali ulashing (keyinroq — modul export i bilan, Nega modullar). Yoki ataylab Symbol.for.
7.4 Symbol kalitni JSON'da kutish
JSON.stringify symbol kalitlarni tashlab yuboradi — xatosiz. Tuzatish: saqlanishi kerak bo'lgan ma'lumot oddiy satr kalitda tursin.
7.5 new Symbol()
TypeError: Symbol is not a constructor. Tuzatish: Symbol("tavsif").
8. Mashqlar
1-mashq (oson): Tavsifli symbol
Symbol("chegirma") yarating. Uning turini, tavsifini va o'zi bilan yangi Symbol("chegirma") tengmi — uchalasini konsolga chiqaring.
Yechim
const chegirma = Symbol("chegirma");
console.log(typeof chegirma); // symbol
console.log(chegirma.description); // chegirma
console.log(chegirma === Symbol("chegirma")); // falseTavsiflar bir xil, lekin symbol'lar — ikki xil qiymat.
2-mashq (o'rta): To'qnashmaydigan belgilar
«Nega bu kerak?» bo'limidagi ikki modulni symbol bilan qayta yozing. Har modul o'z symbol'ini yaratsin va buyurtmaga belgi qo'ysin. So'ng: ikkala belgi saqlanganini, Object.keys va JSON.stringify da ko'rinmasligini ko'rsating.
Yechim
// statistika moduli
const statistikaBelgisi = Symbol("belgi");
// yetkazib berish moduli
const yetkazishBelgisi = Symbol("belgi");
const buyurtma = { id: 17, taom: "osh" };
buyurtma[statistikaBelgisi] = "hisoblandi";
buyurtma[yetkazishBelgisi] = "yo'lda";
console.log(buyurtma[statistikaBelgisi]); // hisoblandi
console.log(buyurtma[yetkazishBelgisi]); // yo'lda
console.log(Object.keys(buyurtma)); // [ 'id', 'taom' ]
console.log(JSON.stringify(buyurtma)); // {"id":17,"taom":"osh"}Ikkala modul ham bexabar holda bir xil tavsif tanladi — "belgi". Muammo yo'q: symbol'lar baribir har xil. Buyurtma serverga ketganda ikkala ichki belgi ham JSON'ga tushmaydi.
3-mashq (qiyin): Buyurtma holatlari
Uch holat konstantasini symbol bilan yarating: QABUL, PISHMOQDA, TAYYOR. keyingiHolat(holat) funksiyasi keyingisini qaytarsin (TAYYOR dan keyin — yana TAYYOR). Noma'lum qiymat kelsa — null. Holatlarni ekranga chiqarishda description ishlating.
Ishora: holatlar tartibini massivda saqlang va indexOf bilan joyini toping.
Yechim
const QABUL = Symbol("qabul qilindi");
const PISHMOQDA = Symbol("pishmoqda");
const TAYYOR = Symbol("tayyor");
const tartib = [QABUL, PISHMOQDA, TAYYOR];
function keyingiHolat(holat) {
const orin = tartib.indexOf(holat);
if (orin === -1) {
return null;
}
return tartib[Math.min(orin + 1, tartib.length - 1)];
}
let holat = QABUL;
for (let i = 0; i < 3; i++) {
console.log(holat.description);
holat = keyingiHolat(holat);
}
console.log(holat.description);
console.log(keyingiHolat("tayyor"));Konsolda:
qabul qilindi
pishmoqda
tayyor
tayyor
nullindexOf symbol'larni === bilan solishtiradi — faqat aynan o'sha symbol topiladi. "tayyor" satri hech qaysi holatga teng emas, shuning uchun null. Math.min oxirgi holatdan oshib ketishga yo'l qo'ymadi (Math obyekti).
4-mashq: Vazifalar qadami — tanlangan vazifalar belgisi (mashqlar repo)
Bu mavzu vazifalar xulqini o'zgartirmaydi — qadam mashqlar reposida: kurs/mashqlar/10/48-symbol/tanlash.mjs.
Kelajakda "bir nechta vazifani tanlab, birdaniga o'chirish" imkoniyati kerak bo'lishi mumkin. Tanlov belgisi vazifa obyektida tursin, lekin eksportga ({ versiya: 1, vazifalar }) va Object.keys ga tushmasin.
TANLANGANsymbol'ini yarating.tanla(vazifa)belgini qo'ysin,tanlanganlar(vazifalar)belgilangan vazifalar massivini qaytarsin.- Eksport matnini
JSON.stringify({ versiya: 1, vazifalar })bilan oling va unda belgi yo'qligini ko'rsating. - O'tgan darsdagi
WeakMapyechimi bilan solishtiring: qaysi biri qachon qulay?
Yechim
const TANLANGAN = Symbol("tanlangan");
function tanla(vazifa) {
vazifa[TANLANGAN] = true;
}
function tanlanganlar(vazifalar) {
return vazifalar.filter((v) => v[TANLANGAN] === true);
}
const vazifalar = [
{ id: 1, matn: "Non olish", bajarildi: false },
{ id: 2, matn: "Choy damlash", bajarildi: true },
{ id: 3, matn: "Kitob o'qish", bajarildi: false },
];
tanla(vazifalar[0]);
tanla(vazifalar[2]);
console.log(tanlanganlar(vazifalar).map((v) => v.id)); // [ 1, 3 ]
console.log(Object.keys(vazifalar[0]));
const eksport = { versiya: 1, vazifalar: [vazifalar[0]] };
console.log(JSON.stringify(eksport));Konsolda:
[ 1, 3 ]
[ 'id', 'matn', 'bajarildi' ]
{"versiya":1,"vazifalar":[{"id":1,"matn":"Non olish","bajarildi":false}]}Belgi vazifaning o'zida, lekin eksportda va Object.keys da yo'q.
Ilovadagi Vazifa klassida (Private maydon va metodlar) toJSON metodi bor — u eksportga faqat uch maydonni o'zi tanlab beradi. Shuning uchun u yerda eksport symbol'siz ham toza qolardi. Symbol esa Object.keys va for...in dan ham yashiradi.
| Symbol kalit | WeakMap |
|
|---|---|---|
| Ma'lumot qayerda | obyektning o'zida | obyekt tashqarisida |
| Muzlatilgan obyekt | yozib bo'lmaydi | ishlaydi |
Nusxa ({ ...v }) |
belgi ham ko'chadi | nusxa — yangi kalit, belgisiz |
| O'qish | v[TANLANGAN] |
jadval.get(v) |
Qoida: obyekt sizniki va nusxalanganda belgi ham ko'chishi kerak bo'lsa — symbol. Obyekt begona yoki muzlatilgan bo'lsa — WeakMap.
Commit (mashqlar repo): 10/48: tanlov belgisini symbol bilan qo'y.
9. Real ishda
- Kutubxona kodi. Immer, Vue va boshqa kutubxonalarda ichki belgilar symbol bilan yoziladi. Ularning manba kodini o'qiganda
Symbol("...")vaSymbol.for("...")ni ko'p uchratasiz. - React. React — interfeys yasash kutubxonasi, kursda alohida o'rganamiz. Uning elementlari
$$typeof: Symbol.for("react.element")belgisi bilan tanilardi (React 19 da —"react.transitional.element"). Bu xavfsizlik uchun: serverdan kelgan JSON'da symbol bo'lmaydi, shuning uchun hujumchi JSON orqali soxta React elementini "yasay olmaydi". - Tilning o'zi.
for...of, spread,instanceof,toString— hammasi ichkarida maxsus symbol'larni so'raydi. Keyingi darsda ularni o'zimiz yozamiz. - Intervyu. "Symbol nima uchun kerak?", "
Symbol()vaSymbol.for()farqi?", "symbol kalitJSON.stringifyda ko'rinadimi?" — ko'p uchraydigan savollar.
Xulosa
Symbol("tavsif")— har safar yangi, noyob primitiv. Tavsif faqat eslatma; unidescriptionberadi.- Symbol satr yoki songa o'zi aylanmaydi —
TypeError.new Symbol()ham xato. - Symbol kalit
[belgi]bilan yoziladi va o'qiladi;Object.keys,for...in,JSON.stringifyuni ko'rmaydi,Object.getOwnPropertySymbolsva spread — ko'radi. - Symbol — yashirin, lekin private emas. Haqiqiy himoya —
#maydon. Symbol.for(kalit)— global registr: bir xil kalit — bir xil symbol. Bunday symbolWeakMapkaliti bo'la olmaydi.
Keyingi dars: Well-known symbols — JavaScript'ning o'zi ishlatadigan taniqli symbol'lar: Symbol.iterator, Symbol.toPrimitive, Symbol.toStringTag va ular orqali obyekt xulqini qanday o'zgartirish.
Manbalar
- MDN: "Symbol", "Symbol.for()", "Object.getOwnPropertySymbols()" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "Symbol Objects", "GlobalSymbolRegistry" — tc39.es/ecma262
- web-features 3.40:
symbol,weakmap(symbol_as_keys) — github.com/web-platform-dx/web-features
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!