IlmHamroh
JavaScript Full-stack/10-qism. JavaScript chuqur48/65-dars15 daqiqa
Mundarija (32)

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 va Object.keys, for...in, JSON.stringify da 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.for va Symbol.keyFor bilan global registrdan foydalana olasiz.
  • Symbol "yashirin", lekin private emasligini va # maydondan farqini tushuntira olasiz.
  • Symbol bilan bog'liq ikki TypeError ni 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:

js
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'lda

Ikkinchi 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:

js
const a = Symbol("belgi");
const b = Symbol("belgi");

console.log(a === b); // false
console.log(a === a); // true
console.log(typeof a); // symbol

a 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:

js
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); // undefined

description — 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

js
const belgi = new Symbol("belgi");
text
TypeError: Symbol is not a constructor

Tarjimasi: "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:

js
const belgi = Symbol("belgi");
console.log(`Kalit: ${belgi}`);
text
TypeError: Cannot convert a Symbol value to a string

Tarjimasi: "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:

js
const belgi = Symbol("belgi");

console.log(`Kalit: ${belgi.description}`); // Kalit: belgi
console.log(String(belgi)); // Symbol(belgi)
console.log(Boolean(belgi)); // true

String(...) — aniq so'rov, u ruxsat etilgan. Mantiqiy qiymatga esa doim true bo'ladi — symbol "truthy".

Tekshirib ko'ring: Symbol("x").description === Symbol("x").description nima 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:

js
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:

text
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:

js
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:

text
[ 'id', 'taom' ]
{"id":17,"taom":"osh"}
id
taom
[ Symbol(hisoblandi) ]
true

Object.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:

js
const belgi = Symbol("belgi");
const asl = { taom: "osh", [belgi]: 1 };

console.log({ ...asl }[belgi]); // 1
console.log(structuredClone(asl)[belgi]); // undefined

Bu 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.stringify symbol kalitni yozmaydi. Ichki belgi serverga yoki faylga tushib qolmaydi.
  • Boshqa kodni buzmaydi. Obyektni Object.keys bilan 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).length va o.x nimaga 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:

js
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:

text
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:

js
const balans = Symbol("balans");
const hamyon = { egasi: "Ali", [balans]: 50000 };

const [topildi] = Object.getOwnPropertySymbols(hamyon);
hamyon[topildi] = 0;

console.log(hamyon[balans]); // 0

Uchta 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:

js
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"))); // undefined

Symbol.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:

js
const kesh = new WeakMap();
kesh.set(Symbol.for("bahor.kesh"), 1);
text
TypeError: Invalid value used as weak map key

Oddiy 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") va Symbol("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:

js
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 holat

Holat 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
js
const chegirma = Symbol("chegirma");

console.log(typeof chegirma); // symbol
console.log(chegirma.description); // chegirma
console.log(chegirma === Symbol("chegirma")); // false

Tavsiflar 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
js
// 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
js
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:

text
qabul qilindi
pishmoqda
tayyor
tayyor
null

indexOf 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.

  1. TANLANGAN symbol'ini yarating. tanla(vazifa) belgini qo'ysin, tanlanganlar(vazifalar) belgilangan vazifalar massivini qaytarsin.
  2. Eksport matnini JSON.stringify({ versiya: 1, vazifalar }) bilan oling va unda belgi yo'qligini ko'rsating.
  3. O'tgan darsdagi WeakMap yechimi bilan solishtiring: qaysi biri qachon qulay?
Yechim
js
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:

text
[ 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("...") va Symbol.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() va Symbol.for() farqi?", "symbol kalit JSON.stringify da ko'rinadimi?" — ko'p uchraydigan savollar.

Xulosa

  • Symbol("tavsif") — har safar yangi, noyob primitiv. Tavsif faqat eslatma; uni description beradi.
  • 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.stringify uni ko'rmaydi, Object.getOwnPropertySymbols va spread — ko'radi.
  • Symbol — yashirin, lekin private emas. Haqiqiy himoya — # maydon.
  • Symbol.for(kalit) — global registr: bir xil kalit — bir xil symbol. Bunday symbol WeakMap kaliti 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
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript Symbol: hech qachon to'qnashmaydigan noyob kalit — IlmHamroh