Symbol Type

...

Symbol Type

Simvol

Standartga ko'ra, ob'ekt xususiyatlari kalitlari sifatida faqat ikkita primitiv turdan foydalanish mumkin:

  • string turi
  • symbol turi

Aks holda, agar boshqa turdan foydalanilsa, masalan, number, avtomatik ravishda string turiga o'zgartiriladi. Shunday qilib, obj[1] obj["1"] ga teng, va obj[true] obj["true"] ga teng.

Hozirgacha biz faqat string turlaridan foydalanganmiz.

Endi, symbol turlarini o'rganamiz va ular bizga nima taklif qilishi mumkinligini ko'rib chiqamiz.

Simvollar

Simvol - bu noyob identifikatorni ifodalaydi.

Bu turdagi qiymat Symbol() yordamida yaratiladi:

let id = Symbol();

Yaratuvchida, simvollarga ta'rif (yoki simvol nomi deb ataladi) berishimiz mumkin, bu asosan debugging maqsadlarida foydalidir:

// id simvoli "id" ta'rifi bilan
let id = Symbol('id');

Simvollar noyob bo'lishi kafolatlangan. Agar biz bir xil ta'rif bilan ko'p simvollar yaratgan bo'lsak, ular turli qiymatlar bo'ladi. Ta'rif - bu faqat yorliq, hech narsani ta'sir qilmaydi.

Masalan, quyidagi ikkita bir xil ta'rifga ega simvollar - ular teng emas:

let id1 = Symbol('id');
let id2 = Symbol('id');
 
alert(id1 == id2); // false

Agar siz Ruby yoki boshqa tilni bilsangiz va unda simvollar mavjud bo'lsa, ehtiyot bo'ling. JavaScript simvollar boshqacha.

Shunday qilib, qisqacha aytganda, simvol - bu “primitiv noyob qiymat” bo'lib, ixtiyoriy ta'rif bilan. Keling, ularni qayerda ishlatishimiz mumkinligini ko'raylik.

Simvollar avtomatik ravishda stringga o'zgarmaydi

JavaScriptdagi ko'p qiymatlar avtomatik ravishda stringga o'zgaradi. Masalan, biz deyarli har qanday qiymatni alert qilishimiz mumkin va bu ishlaydi. Simvollar maxsus. Ular avtomatik ravishda o'zgarish qilmaydi.

Masalan, quyidagi alert xato ko'rsatadi:

let id = Symbol('id');
alert(id); // TypeError: Cannot convert a Symbol value to a string

Bu tilning “xavfsizlik saqlovchisi”, chunki stringlar va simvollar tamoyil jihatdan farq qiladi va bir-biriga avtomatik tarzda o'zgartirilmasligi kerak.

Agar biz simvolni haqiqatan ham ko'rsatmoqchi bo'lsak, toString() metodini aniq chaqirishimiz kerak:

let id = Symbol('id');
alert(id.toString()); // Symbol(id), endi ishlaydi

Yoki faqat ta'rifni ko'rsatish uchun symbol.description xususiyatini olishimiz mumkin:

let id = Symbol('id');
alert(id.description); // id

“Yashirin” xususiyatlar

Simvollar bizga ob'ektning “yashirin” xususiyatlarini yaratish imkonini beradi, bu boshqa kod qismlari tasodifan kirish yoki o'zgartira olmaydi.

Masalan, agar biz foydalanuvchi ob'ektlari bilan ishlayotgan bo'lsak, ular uchinchi tomon kodiga tegishli. Ularning identifikatorlarini qo'shmoqchi bo'lsak.

Simvol kalitidan foydalanamiz:

let user = {
  // boshqa kodga tegishli
  name: 'John',
};
 
let id = Symbol('id');
 
user[id] = 1;
 
alert(user[id]); // biz simvolni kalit sifatida ishlatib ma'lumotga kirishamiz

Nima uchun Symbol("id") ni string "id" dan afzal ko'rishimiz kerak?

Agar foydalanuvchi ob'ektlari boshqa kod bazasiga tegishli bo'lsa, ularga maydon qo'shish xavfsiz emas, chunki biz boshqa kod bazasidagi oldindan belgilangan xatti-harakatlarni ta'sir qilishi mumkin. Biroq, simvollar tasodifan kirish mumkin emas. Uchinchi tomon kodi yangi aniqlangan simvollardan xabardor bo'lmaydi, shuning uchun foydalanuvchi ob'ektlariga simvollarni qo'shish xavfsiz.

Agar boshqa skript foydalanuvchi ichida o'z identifikatorini bo'lishni xohlasa, o'z Symbol("id") ni yaratishi mumkin:

// ...
let id = Symbol('id');
 
user[id] = 'Ularning id qiymati';

Bizning va ularning identifikatorlari o'rtasida hech qanday to'qnashuv bo'lmaydi, chunki simvollar har doim boshqacha, hatto bir xil nomga ega bo'lsa ham.

...Agar biz string "id" ni simvol o'rniga ishlatgan bo'lsak, to'qnashuv bo'ladi:

let user = { name: 'John' };
 
// Bizning skriptimiz "id" maydonini ishlatadi
user.id = 'Bizning id qiymatimiz';
 
// ...Boshqa skript ham "id" ni o'z maqsadlari uchun xohlaydi...
 
user.id = 'Ularning id qiymati';
// Boom! boshqa skript tomonidan o'zgartirildi!

Ob'ekt literalida simvollar

Agar biz simvolni ob'ekt literalida {...} ishlatmoqchi bo'lsak, uni kvadrat qavslar bilan o'rab olishimiz kerak.

Mana shunday:

let id = Symbol('id');
 
let user = {
  name: 'John',
  [id]: 123, // "id": 123 emas
};

Chunki biz id o'zgaruvchidan qiymatni kalit sifatida olishimiz kerak, string “id” emas.

Simvollar for...in orqali o'tkazib yuboriladi

Simvol xususiyatlari for..in tsikliga qo'shilmaydi.

Masalan:

let id = Symbol('id');
let user = {
  name: 'John',
  age: 30,
  [id]: 123,
};
 
for (let key in user) alert(key); // name, age (simvollar yo'q)
 
// simvol orqali to'g'ridan-to'g'ri kirish ishlaydi
alert("To'g'ridan-to'g'ri: " + user[id]); // To'g'ridan-to'g'ri: 123

Object.keys(user) ham ularni e'tiborga olmaydi. Bu umumiy “yashirin simvol xususiyatlarini yashirish” tamoyilining bir qismidir. Agar boshqa skript yoki kutubxona bizning ob'ektimizni aylantirsa, ular tasodifan simvol xususiyatiga kirishmaydi.

Aksincha, Object.assign string va simvol xususiyatlarini ham nusxalaydi:

let id = Symbol('id');
let user = {
  [id]: 123,
};
 
let clone = Object.assign({}, user);
 
alert(clone[id]); // 123

Bu yerda hech qanday paradoks yo'q. Bu dizayn orqali amalga oshirilgan. G'oya shundaki, biz ob'ektni nusxalash yoki birlashtirishda, odatda barcha xususiyatlarni nusxalashni xohlaymiz (simvollar kabi id).

Global simvollar

Ko'rib turganimizdek, odatda barcha simvollar boshqacha, hatto bir xil nomga ega bo'lsa ham. Ammo ba'zan biz bir xil nomli simvollarni bir xil entitiy sifatida ishlatmoqchimiz. Masalan, turli qismlarimiz "id" simvolini aniq bir xususiyatga kirish uchun ishlatishni xohlashi mumkin.

Buni amalga oshirish uchun global simvol ro'yxati mavjud. Biz ro'yxatdan simvollarni yaratishimiz va keyin ularni olishimiz mumkin, va bu takroriy kirishlar bir xil simvolni qaytaradi.

Ro'yxatdan (yoki mavjud bo'lmasa yaratib) simvolni o'qish uchun, Symbol.for(key) dan foydalaning.

Bu chaqiruvi global ro'yxatni tekshiradi, va agar key deb ta'riflangan simvol mavjud bo'lsa, uni qaytaradi, aks holda yangi simvol Symbol(key) yaratadi va uni berilgan kalit bilan ro'yxatda saqlaydi.

Masalan:

// global ro'yxatdan o
 
'qish
let id = Symbol.for("id"); // agar simvol mavjud bo'lmasa, u yaratiladi
 
// uni yana o'qish (boshqa kod qismlaridan)
let idAgain = Symbol.for("id");
 
// bir xil simvol
alert(id === idAgain); // true

Global simvollar deb ataladigan ro'yxatdagi simvollar. Agar biz global darajadagi simvolni istasak, har joyda kodda mavjud bo'lishi – bu maqsad uchun.

Bu Rubyga o'xshaydi

Ba'zi dasturlash tillarida, masalan, Ruby da, bir nomli yagona simvol mavjud.

JavaScriptda, ko'rib turganimizdek, bu global simvollar uchun to'g'ri.

Symbol.keyFor

Global simvollar uchun, Symbol.for(key) simvolni nom bilan qaytaradi. Teskari qilib – global simvoldan nomni olish uchun Symbol.keyFor(sym) dan foydalanishimiz mumkin:

Masalan:

// nom bilan simvol olish
let sym = Symbol.for('name');
let sym2 = Symbol.for('id');
 
// simvoldan nom olish
alert(Symbol.keyFor(sym)); // name
alert(Symbol.keyFor(sym2)); // id

Symbol.keyFor ichida global simvol ro'yxatini ishlatadi, shuning uchun u lokal simvollar uchun ishlamaydi. Agar simvol global bo'lmasa, u topa olmaydi va undefined qaytaradi.

Biroq, barcha simvollar description xususiyatiga ega.

Masalan:

let globalSymbol = Symbol.for('name');
let localSymbol = Symbol('name');
 
alert(Symbol.keyFor(globalSymbol)); // name, global simvol
alert(Symbol.keyFor(localSymbol)); // undefined, global emas
 
alert(localSymbol.description); // name

Tizim simvollar

JavaScript ichida ko'plab “tizim” simvollar mavjud bo'lib, biz ulardan ob'ektlarimizning turli jihatlarini nozik sozlash uchun foydalanishimiz mumkin.

Ular spetsifikatsiyada Well-known symbols jadvalida ro'yxatlangan:

  • Symbol.hasInstance
  • Symbol.isConcatSpreadable
  • Symbol.iterator
  • Symbol.toPrimitive

…va boshqalar.

Masalan, Symbol.toPrimitive ob'ektni primitivga aylantirishni ta'riflash imkonini beradi. Biz uning ishlatilishini tez orada ko'rib chiqamiz.

Boshqa simvollarni ham o'rganamiz, ular bilan til xususiyatlarini o'rganishda tanishamiz.

Xulosa

Simvol - noyob identifikatorlar uchun primitiv tur.

Simvollar Symbol() chaqiruvi bilan yaratiladi va ixtiyoriy ta'rif (nom) bilan birga bo'lishi mumkin.

Simvollar har doim boshqacha qiymatlar, hatto bir xil nomga ega bo'lsa ham. Agar bir xil nomli simvollar bir xil bo'lishini xohlasak, global ro'yxatdan foydalanishimiz kerak: Symbol.for(key) bir xil nom bilan global simvolni qaytaradi (zarur bo'lsa, yaratadi). Bir xil kalit bilan ko'p marta Symbol.for chaqirishi aynan shu simvolni qaytaradi.

Simvollarning ikkita asosiy foydalanish holati mavjud:

  • “Yashirin” ob'ekt xususiyatlari

Agar biz ob'ektga boshqa skript yoki kutubxona tomonidan qo'shmoqchi bo'lsak, simvol yaratib, uni xususiyat kaliti sifatida ishlatamiz. Simvol xususiyati for..in orqali ko'rinmaydi, shuning uchun tasodifan boshqa xususiyatlar bilan birga qayta ishlanmaydi. Shuningdek, uni to'g'ridan-to'g'ri kirish bilan olish mumkin bo'ladi, chunki boshqa skript bizning simvolimizni bilmaydi. Shuning uchun xususiyat tasodifan ishlatilishi yoki o'zgartirilishi mumkin emas.

Shunday qilib, biz ob'ektlarga yashirin tarzda nimadir qo'shishimiz mumkin, lekin boshqalarga ko'rinmaydigan, simvol xususiyatlarini ishlatib.

JavaScriptda mavjud bo'lgan ko'plab tizim simvollar mavjud, ular Symbol.* sifatida kirish mumkin. Biz ularni ba'zi o'rnatilgan xatti-harakatlarni sozlash uchun ishlatishimiz mumkin. Masalan, keyinchalik darslikda biz Symbol.iteratorni iterativlar uchun, Symbol.toPrimitiveni ob'ekt-to-primitiv aylantirish uchun ishlatamiz va boshqalar.

Texnik jihatdan, simvollar 100% yashirin emas. Object.getOwnPropertySymbols(obj) metodi orqali barcha simvollarni olish mumkin. Shuningdek, Reflect.ownKeys(obj) metodi orqali ob'ektning barcha kalitlarini, simvoliklarini ham qo'shib, olish mumkin. Ammo ko'pchilik kutubxonalar, o'rnatilgan funksiyalar va sintaksis konstruktsiyalari bu metodlardan foydalanmaydi.

Ushbu sahifada

GitHubda tahrirlash