Symbol — nima va qachon kerak
Muammodan boshlaylik
Siz katta kutubxona yozdingiz. Foydalanuvchilar uni o'z ob'ektlarida ishlatadi. Kutubxona ob'ektga id xususiyat qo'shishi kerak — ichki maqsad uchun.
Muammo: foydalanuvchining ob'ektida allaqachon id bo'lishi mumkin. Siz id qo'shsangiz — uning qiymatini yozib tashlaysiz.
// Foydalanuvchining ob'ekti
const mahsulot = { id: 42, nomi: "Noutbuk", narx: 8000000 };
// Kutubxona ichki id qo'shmoqchi
mahsulot.id = "ichki-001"; // ❌ — foydalanuvchining id si yo'qoldi!
Symbol — bu muammoni hal qiladi: kalit nom to'qnashuvlari bo'lmaydi.
Symbol nima?
Symbol — yagona va takrorlanmas qiymat. Har yangi Symbol — dunyoda yagona. Hatto bir xil tavsif bilan yaratilsa ham — ular teng emas.
Hayotiy o'xshatma
Pul birliklarini tasavvur qiling. 100 so'mlik ikki tanga — ko'rinishi bir xil, raqami bir xil. Lekin ular ikki alohida tanga — bir xil emas. Symbol ham shunday: tavsifi bir xil bo'lsa ham — har biri yagona.
const a = Symbol("id");
const b = Symbol("id");
console.log(a === b); // false ← bir xil tavsif, lekin turli Symbol
console.log(typeof a); // "symbol"
console.log(a.toString()); // "Symbol(id)"
console.log(a.description); // "id" ← tavsif
Symbol kalit sifatida
Symbol ning asosiy kuchi — ob'ekt xususiyati kalit sifatida ishlatish. Symbol kalit — oddiy matn kalit bilan to'qnashmaydi.
const ICHKI_ID = Symbol("id"); // ← kutubxona yaratdi
const mahsulot = {
id: 42, // ← foydalanuvchining id si
nomi: "Noutbuk",
[ICHKI_ID]: "ichki-001", // ← kutubxonaning ichki id si
};
console.log(mahsulot.id); // 42 ← o'zgarmadi ✅
console.log(mahsulot[ICHKI_ID]); // "ichki-001" ✅
To'qnashuv yo'q — chunki Symbol yagona. Hech kim sizning ICHKI_ID Symbol ini qaytadan yaratolmaydi.
Symbol lar ko'rinmaydi — "yashirin" xususiyatlar
Symbol xususiyatlar oddiy ko'rishda chiqmaydi:
const ID = Symbol("id");
const ob = { ism: "Jasur", [ID]: 42 };
// Oddiy usullar Symbol ni ko'rmaydi
console.log(Object.keys(ob)); // ["ism"] ← ID yo'q
console.log(Object.values(ob)); // ["Jasur"] ← 42 yo'q
console.log(JSON.stringify(ob)); // '{"ism":"Jasur"}' ← ID yo'q
for (const kalit in ob) {
console.log(kalit); // faqat "ism" ← ID ko'rinmaydi
}
// Symbol larga maxsus usul bilan kirish
console.log(Object.getOwnPropertySymbols(ob)); // [Symbol(id)]
console.log(ob[ID]); // 42 ← to'g'ridan kirish
Bu xususiyat kutubxonalar uchun qulay — ichki ma'lumot foydalanuvchi for...in yoki JSON.stringify bilan ko'rmaydi.
Symbol.for — global registry
Turli fayllarda bir xil Symbol kerak bo'lsa — Symbol.for global registrdan oladi:
// a.js faylida
const A = Symbol.for("umumiy-id");
// b.js faylida — boshqa fayl, lekin bir xil Symbol
const B = Symbol.for("umumiy-id");
console.log(A === B); // true ← global registrdan, bir xil
// Oddiy Symbol bilan farqi:
const C = Symbol("umumiy-id");
console.log(A === C); // false ← lokal, boshqa
Symbol.for — "bu nom bilan allaqachon Symbol bor? Bergin. Yo'q bo'lsa — yaratgin."
O'rnatilgan Symbol lar — JavaScript ning o'zi ishlatadi
JavaScript ichki mexanizmlari ham Symbol ishlatadi. Siz ularni override qilish orqali ob'ektlaringiz xulqini o'zgartira olasiz.
Oldingi darsda ko'rgan [Symbol.iterator] — shulardan biri:
// for...of qanday ishlashini o'zgartirish
const ob = {
malumotlar: [10, 20, 30],
[Symbol.iterator]() { // ← JavaScript shu metodga murojaat qiladi
let i = 0;
return {
next: () => ({
value: this.malumotlar[i],
done: i++ >= this.malumotlar.length,
})
};
}
};
for (const qiymat of ob) {
console.log(qiymat); // 10, 20, 30
}
Boshqa muhim o'rnatilgan Symbol lar:
Symbol.toPrimitive — ob'ekt oddiy qiymatga (son, matn) o'zgartirilganda:
const narx = {
qiymat: 50000,
valyuta: "so'm",
[Symbol.toPrimitive](hint) {
if (hint === "number") return this.qiymat;
if (hint === "string") return `${this.qiymat} ${this.valyuta}`;
return this.qiymat;
}
};
console.log(+narx); // 50000 ← hint: "number"
console.log(`${narx}`); // "50000 so'm" ← hint: "string"
console.log(narx + 1000); // 51000 ← hint: "default"
Symbol.hasInstance — instanceof xulqini o'zgartirish:
class SonlarTo_plami {
static [Symbol.hasInstance](qiymat) {
return typeof qiymat === "number";
}
}
console.log(42 instanceof SonlarTo_plami); // true
console.log("matn" instanceof SonlarTo_plami); // false
Tez-tez uchraydigan xatolar
Symbol ni new bilan yaratish:
// ❌ — Symbol konstruktor emas
const s = new Symbol("id"); // TypeError: Symbol is not a constructor
// ✅ — funksiya sifatida chaqiriladi
const s = Symbol("id");
Symbol ni JSON ga o'girish mumkin emas:
const ID = Symbol("id");
const ob = { ism: "Jasur", [ID]: 42 };
JSON.stringify(ob); // '{"ism":"Jasur"}' — Symbol yo'qoldi
Symbol xususiyatlar JSON da yo'qoladi. Agar ma'lumot serverga yuborilishi kerak bo'lsa — oddiy matn kalit ishlatish kerak.
Symbol() va Symbol.for() ni aralashtirish:
const a = Symbol("test"); // ← lokal, yagona
const b = Symbol.for("test"); // ← global registry dan
const c = Symbol.for("test"); // ← registry da bor — b bilan bir xil
console.log(a === b); // false
console.log(b === c); // true
Xulosa
Symbol — yagona va takrorlanmas qiymat. Har yangi Symbol dunyo da yagona.
Ob'ekt xususiyati kalit sifatida — matn kalitlar bilan to'qnashmaydi. for...in, Object.keys, JSON.stringify ko'rmaydi — "yashirin" xususiyat.
Symbol.for — global registry. Turli fayllarda bir xil Symbol olish uchun.
O'rnatilgan Symbol lar — Symbol.iterator, Symbol.toPrimitive, Symbol.hasInstance — JavaScript ning ichki mexanizmlarini o'zgartirish uchun.
Asosiy ishlatilishi: kutubxonalarda to'qnashuvsiz ichki xususiyatlar va ob'ekt xulqini sozlash.
Keyingi dars
60-dars: Proxy va Reflect