Mundarija (33)
- Bu darsda
- 1. Nega bu kerak?
- 2. Well-known symbol nima?
- 2.1 Symbol ning statik xususiyatlari
- 2.2 Til qachon qaysi symbol'ni so'raydi
- 3. Symbol.toPrimitive — songa va satrga aylanish
- 3.1 Eslab olamiz: ishora (hint)
- 3.2 Qaror qanday qabul qilinadi
- 3.3 valueOf bilan birga bo'lsa
- 3.4 Qachon kerak
- 4. Symbol.toStringTag — obyekt turining nomi
- 5. Symbol.iterator — for...of ning kaliti
- 5.1 Kim aylanadi, kim yo'q
- 5.2 Metod nima qaytaradi — bir qarash
- 5.3 Qiymat aylanadimi — tekshirish
- 5.4 Oddiy yo'l: massivning iteratoriga topshirish
- 6. Symbol.hasInstance va Symbol.species
- 6.1 instanceof ni o'zgartirish
- 6.2 Meros klassda map nima qaytaradi
- 7. Qolgan taniqli symbol'lar
- 8. Ko'p uchraydigan xatolar
- 8.1 Symbol.toPrimitive obyekt qaytaradi
- 8.2 Kalitni satr bilan yozish
- 8.3 Symbol.iterator iterator emas, massiv qaytaradi
- 8.4 Yashirin xulqni haddan ziyod ishlatish
- 9. Mashqlar
- 1-mashq (oson): Haroratli obyekt
- 2-mashq (o'rta): Tur nomi va aylanish
- 3-mashq (qiyin): Pul obyekti
- 4-mashq: Vazifalar qadami — "o'zini tanitadigan" vazifa (mashqlar repo)
- 10. Real ishda
- Xulosa
- Manbalar
Well-known symbols: Symbol.iterator, Symbol.toPrimitive va obyekt xulqini sozlash
Qisqacha: Well-known symbols — JavaScript'ning o'zi tayyorlab qo'ygan symbol'lar:
Symbol.iterator,Symbol.toPrimitive,Symbol.toStringTagva boshqalar. Tilfor...of,+,${},instanceofkabi amallarni bajarishdan oldin obyektdan shu kalitli metodni so'raydi. Obyektga shunday metod yozsangiz, u til darajasidagi xulqini o'zgartiradi: masalan,[Symbol.toPrimitive](hint)obyekt songa va satrga qanday aylanishini hal qiladi.
Bu darsda
- Well-known symbol nima ekanini va til ularni qachon "so'rashini" tushuntira olasiz.
Symbol.toPrimitivebilan obyektning songa va satrga aylanishini boshqara olasiz.Symbol.toStringTagbilan obyekt turining nomini bera olasiz.Symbol.iteratornegafor...ofva spread'ning kaliti ekanini ko'rasiz va obyektni massiv orqali "aylanadigan" qila olasiz.Symbol.hasInstance,Symbol.speciesva qolgan symbol'larni tanib olasiz.
Oldin bilishingiz kerak: Symbol, Yashirin coercion qoidalari ichidan, class sintaksisi, Getter/setter va static a'zolar, Object.create va instanceof.
1. Nega bu kerak?
Set darsida bitta xato xabarida g'alati nom ko'rgan edik:
TypeError: number 5 is not iterable (cannot read property Symbol(Symbol.iterator))Yashirin coercion darsida esa "valueOf va toString dan ham kuchliroq yo'l bor — Symbol.toPrimitive" deb va'da bergan edik. Object.create va instanceof darsida — Symbol.hasInstance.
Uchala joyda ham bitta g'oya yashiringan. JavaScript for...of, + yoki instanceof ni bajarayotganda obyektga "savol beradi". Savol — maxsus symbol kalitli metodni qidirish. Metod bo'lsa — til uni chaqiradi. Bo'lmasa — odatiy xulq.
Hayotdan o'xshatish: mehmonxona qabulxonasi. Har mehmondan "maxsus iltimosingiz bormi?" deb so'rashadi. Iltimos yozilgan bo'lsa — ertalab aynan siz aytgandek uyg'otishadi. Yozilmagan bo'lsa — hammaga bir xil tartib. Well-known symbol — o'sha "iltimos varaqasi"ning standart bandlari. Ularni to'ldirib, siz tilning o'ziga obyektingiz bilan qanday ishlashni aytasiz.
2. Well-known symbol nima?
2.1 Symbol ning statik xususiyatlari
O'tgan darsda Symbol ni o'zimiz yaratdik. Lekin ba'zi symbol'lar tilning ichida allaqachon yaratilgan. Ular Symbol funksiyasining statik xususiyatlari sifatida turadi:
const nomlar = Object.getOwnPropertyNames(Symbol).filter(
(nom) => typeof Symbol[nom] === "symbol",
);
console.log(nomlar.length); // 15
console.log(Symbol.iterator); // Symbol(Symbol.iterator)
console.log(Symbol.keyFor(Symbol.iterator)); // undefinedWell-known symbol ("taniqli symbol") — til spetsifikatsiyasida nomi va vazifasi belgilangan, hamma uchun bitta tayyor symbol. Node 24 da ular 15 ta. Ular Symbol.for registrida emas (keyFor — undefined), lekin hamma joyda bir xil: sizning faylingizdagi Symbol.iterator va kutubxonadagi Symbol.iterator — aynan bitta qiymat.
2.2 Til qachon qaysi symbol'ni so'raydi
Sxemada chapda — siz yozadigan oddiy amal, o'ngda — til o'sha paytda obyektdan qidiradigan metod:
flowchart LR
A["for...of, spread,<br/>new Set(x)"] --> I["Symbol.iterator"]
B["x * 2, x + 1,<br/>shablon satr"] --> P["Symbol.toPrimitive"]
C["String(x) → [object …]"] --> T["Symbol.toStringTag"]
D["x instanceof K"] --> H["Symbol.hasInstance"]
E["arr.map(), filter()<br/>meros klassda"] --> S["Symbol.species"]Har biri — tilning bitta "eshigi". Bu darsda shu beshtasini ko'rib chiqamiz. Qolganlarini (for await...of uchun Symbol.asyncIterator, using uchun Symbol.dispose va boshqalar) tanib olish uchun dars oxiridagi jadvalda beramiz.
3. Symbol.toPrimitive — songa va satrga aylanish
3.1 Eslab olamiz: ishora (hint)
Yashirin coercion darsida obyekt primitivga aylanayotganda til ishora (hint) berishini ko'rdik: "son kerak" (number), "satr kerak" (string) yoki "farqi yo'q" (default). Keyin valueOf va toString ni ishoraga qarab har xil tartibda chaqiradi.
Symbol.toPrimitive bu ikki metodni chetlab o'tadi. Obyektda shu kalitli metod bo'lsa, til ishorani to'g'ridan-to'g'ri unga beradi:
const summa = {
qiymat: 35000,
[Symbol.toPrimitive](hint) {
console.log("hint:", hint);
return hint === "string" ? "35 000 so'm" : this.qiymat;
},
};
console.log(summa * 2);
console.log(`${summa}`);
console.log(summa + 1000);Konsolda:
hint: number
70000
hint: string
35 000 so'm
hint: default
36000Har amal metodni o'z ishorasi bilan chaqirdi:
summa * 2— ko'paytirish faqat son bilan ishlaydi:number.`${summa}`— shablon satr:string.summa + 1000—+ham qo'shish, ham satr ulash bo'lishi mumkin:default. Bizning metoddefaultda son qaytardi.
Metod nomi kvadrat qavsda — computed kalit, xuddi o'tgan darsdagi symbol kalitlar kabi.
E'tibor bering: biz metodni hech qayerda o'zimiz chaqirmadik. Uni til chaqirdi — *, ${} yoki + ni bajarishdan oldin. Keyingi tugmasini bosib, birinchi qatorda nima ketma-ket bo'lishini kuzating:
Tartib muhim: avval hint: number, keyin 70000. Metod ko'paytirishdan oldin ishladi, chunki ko'paytirishga son kerak edi.
3.2 Qaror qanday qabul qilinadi
Coercion darsidagi qoidalar endi to'liq ko'rinishga ega. Sxemani yuqoridan pastga o'qing:
flowchart TD
S["Obyekt primitiv bo'lishi kerak<br/>(hint: number / string / default)"]
S --> Q{"Symbol.toPrimitive bormi?"}
Q -- "ha" --> T["uni hint bilan chaqir"]
T --> R{"Natija primitivmi?"}
R -- "ha" --> OK["tayyor"]
R -- "yo'q" --> X["TypeError"]
Q -- "yo'q" --> H{"hint = string?"}
H -- "ha" --> TS["avval toString, keyin valueOf"]
H -- "yo'q" --> VO["avval valueOf, keyin toString"]Symbol.toPrimitive primitiv qaytarishi shart. Obyekt qaytarsa:
const yomon = {
[Symbol.toPrimitive]() {
return {};
},
};
console.log(yomon + 1);TypeError: Cannot convert object to primitive valueTarjimasi: "Obyektni primitiv qiymatga aylantirib bo'lmaydi". Til metodni chaqirdi, javob yana obyekt bo'ldi — davom etishga imkon yo'q. valueOf/toString dagidek "ikkinchi urinish" yo'q.
3.3 valueOf bilan birga bo'lsa
Obyektda uchala metod ham bo'lsa-chi? Sxemadagi birinchi savol hal qiladi — Symbol.toPrimitive g'olib, qolgan ikkitasiga umuman qaralmaydi:
const hamyon = {
valueOf() {
return 1;
},
toString() {
return "eski";
},
[Symbol.toPrimitive]() {
return 50000;
},
};
console.log(hamyon + 0); // 50000
console.log(`${hamyon}`); // 50000Coercion darsidagi hamyon misoli valueOf va toString ga tayangan edi. Endi uchinchi, eng kuchli qatlam qo'shildi. Shablon satrda ham 50000 chiqdi: metod ishorani e'tiborga olmadi va doim son qaytardi. Ishorani hisobga olish — metodning o'z ishi.
3.4 Qachon kerak
Coercion darsidagi Date istisnosini eslang: sana + 1 satr beradi. Bu Date ning o'zida aynan Symbol.toPrimitive yozilgani uchun — u default ishorani string deb qabul qiladi:
const sana = new Date(0);
console.log(typeof (sana + 1)); // string
console.log(sana[Symbol.toPrimitive]("number")); // 0O'z kodingizda Symbol.toPrimitive — "pul", "o'lchov", "vaqt oralig'i" kabi qiymat obyektlari uchun: son sifatida hisob-kitobda, satr sifatida ekranda. Lekin ehtiyot bo'ling. Yashirin aylanish kodni sirli qiladi: summa + 1000 ni o'qigan odam ichida metod borligini bilmaydi. Ko'p jamoalar aniq metodni afzal ko'radi: summa.son(), summa.matn(). Symbol.toPrimitive ni kutubxona yoki juda ko'p ishlatiladigan obyekt uchun saqlang.
Tekshirib ko'ring: Yuqoridagi
summauchunString(summa)vasumma == 35000qaysi ishora bilan chaqiradi?
Javob
String(summa) — string ishora, natija "35 000 so'm". summa == 35000 — default ishora (== ham "farqi yo'q" so'raydi), natija 35000, demak true. Ikkalasini konsolda sinab, hint: qatoriga qarang.
4. Symbol.toStringTag — obyekt turining nomi
Obyektni satrga aylantirsangiz, odatda [object Object] chiqadi. Lekin o'rnatilgan obyektlarda boshqacha:
const nomi = (x) => Object.prototype.toString.call(x);
console.log(nomi([])); // [object Array]
console.log(nomi(new Map())); // [object Map]
console.log(nomi(null)); // [object Null]
console.log(nomi({})); // [object Object]Object.prototype.toString — eng aniq tur aniqlash usullaridan biri (typeof va turni to'g'ri aniqlash darsida typeof null muammosini ko'rgan edik). Qavslar ichidagi ikkinchi so'zni u Symbol.toStringTag dan oladi. Uni o'z klassingizga ham berish mumkin — odatda getter sifatida:
class Savat {
get [Symbol.toStringTag]() {
return "Savat";
}
}
const s = new Savat();
console.log(String(s)); // [object Savat]
console.log(`${s}`); // [object Savat]Foydasi — xato xabarlari va loglarda. [object Object] o'rniga [object Savat] — qaysi obyekt ekanini darhol ko'rasiz. Node konsoli ham bu nomni ko'rsatadi, agar u klass nomidan farq qilsa. Masalan, Savat klassining getter'i "Buyurtma" qaytarsa, console.log(new Savat()) — Savat [Buyurtma] {}: avval klass nomi, kvadrat qavsda — teg.
E'tibor bering: toStringTag faqat nom beradi, obyektning turini o'zgartirmaydi. typeof baribir "object", instanceof Map baribir false. Shu sababli bu nomga xavfsizlik tekshiruvida tayanmang — istalgan obyekt o'zini "Map" deb atashi mumkin.
Tekshirib ko'ring:
SavatklassidatoStringTaggetter'i bo'lmasa,String(new Savat())nima beradi?
Javob
[object Object]. Object.prototype.toString Symbol.toStringTag ni topmadi va odatiy Object nomini ishlatdi. Klass nomi o'z-o'zidan teg bo'lib qolmaydi — uni getter bilan berish kerak.
5. Symbol.iterator — for...of ning kaliti
5.1 Kim aylanadi, kim yo'q
for...of massiv, satr, Map va Set da ishlaydi, oddiy obyektda esa yo'q:
const narxlar = { osh: 35000, manti: 30000 };
for (const narx of narxlar) {
console.log(narx);
}TypeError: narxlar is not iterableTarjimasi: "narxlar — aylanib chiqib bo'lmaydigan (iterable emas)". Nega? Farq bitta metodda:
console.log(typeof [][Symbol.iterator]); // function
console.log(typeof "osh"[Symbol.iterator]); // function
console.log(typeof new Map()[Symbol.iterator]); // function
console.log(typeof {}[Symbol.iterator]); // undefinedfor...of boshlanishidan oldin til obyektdan Symbol.iterator metodini so'raydi. Massivda, satrda, Map da u bor — oddiy obyektda yo'q. Spread ([...x]), massiv destructuring, new Set(x), Array.from(x) ham aynan shu metodni so'raydi. Shuning uchun new Set(5) xatosida Symbol(Symbol.iterator) nomi chiqqan edi.
5.2 Metod nima qaytaradi — bir qarash
Bu metodni qo'lda chaqirib ko'ramiz:
const navbat = ["osh", "manti"];
const iterator = navbat[Symbol.iterator]();
console.log(iterator.next()); // { value: 'osh', done: false }
console.log(iterator.next()); // { value: 'manti', done: false }
console.log(iterator.next()); // { value: undefined, done: true }U iterator qaytardi — next() metodli obyekt. Har next() navbatdagi qiymatni va "tugadimi?" (done) belgisini beradi. for...of ichkarida aynan shunday qiladi: done: true bo'lguncha next() ni chaqiradi. Map darsida ko'rgan [Map Iterator] ham shunday obyekt edi.
Bu kelishuvning to'liq qoidalari — "iteratsiya protokoli" — keyingi darsning mavzusi. O'z iteratoringizni noldan yozish — undan keyingi darsda. Hozircha bitta narsani biling: Symbol.iterator — kalit, iterator — u qaytaradigan obyekt.
5.3 Qiymat aylanadimi — tekshirish
Funksiya "aylanadigan" narsa kutsa, uni oldindan tekshirish mumkin. Qoida bitta: Symbol.iterator kalitida funksiya bormi?
function aylanadimi(x) {
return typeof x?.[Symbol.iterator] === "function";
}
console.log(aylanadimi([1, 2])); // true
console.log(aylanadimi("osh")); // true
console.log(aylanadimi(new Set())); // true
console.log(aylanadimi({ osh: 1 })); // false
console.log(aylanadimi(5)); // false
console.log(aylanadimi(null)); // false?. — null va undefined da xato chiqmasligi uchun (??, ?. va mantiqiy tayinlash). Satr ham true berdi: satr aylanadi, uning elementlari — harflar. Set darsidagi new Set("salom") tuzog'i aynan shundan. Son esa primitiv, lekin uning o'rami Number.prototype da Symbol.iterator yo'q — false.
Nomi "-mi" bilan — u predikat, true/false qaytaradi.
5.4 Oddiy yo'l: massivning iteratoriga topshirish
Iteratorni o'zingiz yozmasdan ham, obyektni aylanadigan qilish mumkin. Ichida massiv saqlaydigan klass shu massivning iteratorini qaytarsa bo'ldi:
class Menyu {
#taomlar = ["osh", "lag'mon", "manti"];
[Symbol.iterator]() {
return this.#taomlar[Symbol.iterator]();
}
}
const menyu = new Menyu();
for (const taom of menyu) {
console.log(taom);
}
console.log([...menyu].length); // 3Konsolda:
osh
lag'mon
manti
3Menyu endi for...of, spread, new Set(menyu), Array.from(menyu) bilan ishlaydi — barchasi bitta metod tufayli. Private #taomlar tashqariga massiv sifatida chiqmaydi: tashqaridagi kod uni faqat aylanib o'qiy oladi, push qila olmaydi.
Tekshirib ko'ring:
Menyudagi[Symbol.iterator]metodini olib tashlasak,[...menyu]nima beradi?
Javob
TypeError: menyu is not iterable. Spread Symbol.iterator ni qidiradi, klassda va uning prototip zanjirida u yo'q. Private #taomlar massivi ichkarida turgani yordam bermaydi — til faqat bitta kalitga qaraydi.
6. Symbol.hasInstance va Symbol.species
6.1 instanceof ni o'zgartirish
Object.create va instanceof darsida instanceof prototip zanjiri bo'yicha ishlashini ko'rdik va Symbol.hasInstance ni bir gap bilan esladik. O'ng tomondagi klassda shu statik metod bo'lsa, til zanjirga qaramaydi — metodni chaqiradi:
class JuftSon {
static [Symbol.hasInstance](x) {
return Number.isInteger(x) && x % 2 === 0;
}
}
console.log(4 instanceof JuftSon); // true
console.log(3 instanceof JuftSon); // false4 hech qanday klass nusxasi emas, lekin instanceof true berdi. Bu kuchli, lekin chalkashtiradigan imkoniyat — kod o'quvchisi instanceof ni prototip zanjiri deb tushunadi. Amalda u juda kam ishlatiladi. Biling, lekin o'z kodingizda tekshiruvni oddiy nomli funksiya bilan yozing: juftmi(x).
6.2 Meros klassda map nima qaytaradi
Meros: extends va super darsida massivdan meros olgan klassni ko'rgan edik. Uning nusxasida map, filter chaqirilsa, natija ham o'sha klass bo'ladi:
class Royxat extends Array {}
const r = Royxat.from([1, 2, 3]);
const ikki = r.map((x) => x * 2);
console.log(ikki instanceof Royxat); // true
console.log(ikki); // Royxat(3) [ 2, 4, 6 ]Massiv metodi yangi massivni qaysi klass bilan yasashni Symbol.species dan so'raydi. Odatda bu — nusxaning o'z klassi. Natija oddiy Array bo'lishini istasangiz, statik getter yozasiz:
class Royxat extends Array {
static get [Symbol.species]() {
return Array;
}
}
const ikki = Royxat.from([1, 2]).map((x) => x * 2);
console.log(ikki instanceof Royxat); // false
console.log(ikki); // [ 2, 4 ]Symbol.species ham kam uchraydi va standartdan olib tashlash muhokama qilingan — u dvigatellarni sekinlashtiradi va xavfsizlik muammolariga sabab bo'lgan. Biling, lekin o'zingiz yozmang.
7. Qolgan taniqli symbol'lar
Tanib olish uchun — qisqa jadval:
| Symbol | Til uni qachon so'raydi | Qayerda o'rganamiz |
|---|---|---|
Symbol.asyncIterator |
for await...of — asinxron aylanish |
11-qism, asinxron JavaScript |
Symbol.dispose, asyncDispose |
using — resursni avtomatik yopish |
using |
Symbol.isConcatSpreadable |
concat obyektni yoyadimi |
— (juda kam) |
Symbol.match, matchAll, replace, search, split |
satr metodlari argumentni "regex" (matn naqshi) deb ishlatadimi | RegExp asoslari |
Symbol.unscopables |
eski with operatori |
— (tarixiy) |
with — bugun ishlatilmaydigan eski operator, qat'iy rejimda umuman taqiqlangan. Symbol.unscopables ga bir qarash qiziq: massiv prototipida u toSorted, flat, includes kabi yangi metodlar ro'yxatini saqlaydi. Bu ham "eski saytlarni buzmaslik" uchun — eski with kodida bu nomlar oddiy o'zgaruvchi bo'lib qolishi kerak edi. O'tgan darsdagi g'oyaning yana bir ko'rinishi: til yangilanadi, eski kod buzilmaydi.
8. Ko'p uchraydigan xatolar
8.1 Symbol.toPrimitive obyekt qaytaradi
TypeError: Cannot convert object to primitive value. Tuzatish: har ishorada son, satr yoki boolean qaytaring.
8.2 Kalitni satr bilan yozish
const obyekt = {
"Symbol.iterator"() {
return [1, 2][Symbol.iterator]();
},
};
console.log(typeof obyekt[Symbol.iterator]); // undefined"Symbol.iterator" — oddiy satr nom, til uni so'ramaydi. Tuzatish: [Symbol.iterator]() — kvadrat qavs ichida symbol'ning o'zi.
8.3 Symbol.iterator iterator emas, massiv qaytaradi
[Symbol.iterator]() { return this.#taomlar; } — massivning o'zi qaytarildi, unda next() yo'q. for...of darhol TypeError: undefined is not a function beradi: til next ni chaqirmoqchi bo'ldi, u esa undefined edi. Xabar Symbol.iterator haqida hech narsa demaydi — shuning uchun bu xatoni topish qiyin. Tuzatish: this.#taomlar[Symbol.iterator]() — oxiridagi qavslar bilan, metodni chaqirib.
8.4 Yashirin xulqni haddan ziyod ishlatish
Symbol.toPrimitive yoki Symbol.hasInstance bilan obyekt "aqlli" bo'lib qoladi, lekin kodni o'qigan odam kutmagan narsa sodir bo'ladi. Tuzatish: oddiy nomli metod (summa.matn()) yetsa — shuni yozing.
9. Mashqlar
1-mashq (oson): Haroratli obyekt
harorat obyekti yarating: daraja: 23. Symbol.toPrimitive bilan: satr kerak bo'lganda "23 °C", aks holda — son. `Toshkentda ${harorat}` va harorat + 2 ni chiqaring.
Yechim
const harorat = {
daraja: 23,
[Symbol.toPrimitive](hint) {
return hint === "string" ? `${this.daraja} °C` : this.daraja;
},
};
console.log(`Toshkentda ${harorat}`); // Toshkentda 23 °C
console.log(harorat + 2); // 25Shablon satr string ishora beradi, + esa default — u holda son qaytardik.
2-mashq (o'rta): Tur nomi va aylanish
Navbat klassini yozing: ichida private #mijozlar massivi, qosh(ism) metodi. Klass:
String(navbat)da[object Navbat]bersin (Symbol.toStringTag);for...ofva spread bilan aylansin (Symbol.iterator— massivga topshiring).
Yechim
class Navbat {
#mijozlar = [];
qosh(ism) {
this.#mijozlar.push(ism);
}
get [Symbol.toStringTag]() {
return "Navbat";
}
[Symbol.iterator]() {
return this.#mijozlar[Symbol.iterator]();
}
}
const navbat = new Navbat();
navbat.qosh("Jasur aka");
navbat.qosh("Nodira");
console.log(String(navbat)); // [object Navbat]
console.log([...navbat]); // [ 'Jasur aka', 'Nodira' ]
for (const ism of navbat) {
console.log(`Kutilmoqda: ${ism}`);
}Konsolda:
[object Navbat]
[ 'Jasur aka', 'Nodira' ]
Kutilmoqda: Jasur aka
Kutilmoqda: NodiraIkki getter/metod — ikki "eshik". #mijozlar tashqariga chiqmadi: spread yangi massiv yasadi.
3-mashq (qiyin): Pul obyekti
Som klassini yozing: constructor(son), Symbol.toPrimitive — number va default da son, string da minglik bo'shliq bilan va "so'm" bilan ("35 000 so'm"). Formatlashni o'zingiz yozing: toLocaleString Node va Chrome'da har xil natija beradi (Pul va aniq hisob-kitob darsidagi ogohlantirish).
Sinang: `${new Som(35000)}`, new Som(35000) * 2, new Som(1250000) > new Som(999000).
Ishora: minglikka bo'lish — sonni satrga aylantirib, oxiridan uchtadan kesib borish (Kesish, bo'lish va to'ldirish).
Yechim
function minglik(son) {
const raqamlar = String(son);
const qismlar = [];
for (let oxir = raqamlar.length; oxir > 0; oxir -= 3) {
qismlar.unshift(raqamlar.slice(Math.max(0, oxir - 3), oxir));
}
return qismlar.join(" ");
}
class Som {
constructor(son) {
this.son = son;
}
[Symbol.toPrimitive](hint) {
if (hint === "string") {
return `${minglik(this.son)} so'm`;
}
return this.son;
}
}
console.log(`${new Som(35000)}`); // 35 000 so'm
console.log(new Som(35000) * 2); // 70000
console.log(new Som(1250000) > new Som(999000)); // true
console.log(`${new Som(500)}`); // 500 so'm> taqqoslash number ishora beradi — ikkala obyekt songa aylanib solishtirildi. minglik oxiridan uchtadan kesadi: 1250000 → "1", "250", "000". 500 kabi qisqa sonda sikl bir marta ishlaydi.
4-mashq: Vazifalar qadami — "o'zini tanitadigan" vazifa (mashqlar repo)
Bu mavzu vazifalar ilovasi xulqini o'zgartirmaydi — qadam mashqlar reposida: kurs/mashqlar/10/49-well-known/vazifa.mjs.
Ilovadagi Vazifa klassining soddalashtirilgan nusxasini oling (id, #matn va matn getter'i, bajarildi). Unga uch "eshik" qo'shing:
Symbol.toPrimitive: satr kerak bo'lganda"[x] Non olish"yoki"[ ] Non olish"(bajarilganmi-yo'qmi), son kerak bo'lganda —id.Symbol.toStringTag—"Vazifa".Royxatklassi: ichida vazifalar massivi,qosh(vazifa)vaSymbol.iterator(massivga topshirish).
So'ng: ro'yxatni for...of bilan shablon satr orqali chiqaring va id bo'yicha saralang.
Yechim
class Vazifa {
#matn;
constructor(id, matn, bajarildi = false) {
this.id = id;
this.#matn = matn;
this.bajarildi = bajarildi;
}
get matn() {
return this.#matn;
}
[Symbol.toPrimitive](hint) {
if (hint === "string") {
return `[${this.bajarildi ? "x" : " "}] ${this.#matn}`;
}
return this.id;
}
get [Symbol.toStringTag]() {
return "Vazifa";
}
}
class Royxat {
#vazifalar = [];
qosh(vazifa) {
this.#vazifalar.push(vazifa);
}
[Symbol.iterator]() {
return this.#vazifalar[Symbol.iterator]();
}
}
const royxat = new Royxat();
royxat.qosh(new Vazifa(3, "Onamga qo'ng'iroq qilish"));
royxat.qosh(new Vazifa(1, "Non olish"));
royxat.qosh(new Vazifa(2, "DOM darsini takrorlash", true));
for (const v of royxat) {
console.log(`${v}`);
}
const tartibda = [...royxat].toSorted((a, b) => a - b);
console.log(tartibda.map((v) => v.id));
console.log(Object.prototype.toString.call(tartibda[0]));Konsolda:
[ ] Onamga qo'ng'iroq qilish
[ ] Non olish
[x] DOM darsini takrorlash
[ 1, 2, 3 ]
[object Vazifa](a, b) => a - b — sort darsidagi son taqqoslash. Ayirish number ishora berdi, vazifalar id'ga aylandi. Bu qisqa, lekin sirli: kod o'quvchisi a - b vazifalar uchun nima ekanini bilmaydi. Ilovaning o'zida (a, b) => a.id - b.id yozgan ma'qul — «Yashirin xulqni haddan ziyod ishlatish» bo'limidagi qoida.
Royxat dagi Symbol.iterator — Iteratsiya protokoli darsiga ko'prik: u yerda next() ni o'zimiz yozib, nima bo'layotganini to'liq ko'ramiz.
Commit (mashqlar repo): 10/49: Vazifa ga toPrimitive, toStringTag va iterator.
10. Real ishda
- Har kuni — bilmasdan.
for...of, spread,Array.from,new Map(...)— har biriSymbol.iteratorni ishlatadi. DOM'dagiNodeList,FormData,URLSearchParamsham shu metod tufaylifor...ofbilan aylanadi. - Kutubxonalar. Immutable.js kabi kutubxonalar (o'zgarmas to'plamlar beradi; hozir bilish shart emas) o'z to'plamlariga
Symbol.iteratorberadi — siz ularni massivdek aylanasiz.Temporal— sana va vaqt bilan ishlashning yangi standart vositasi. Uning obyektlariSymbol.toStringTagbilan o'zini tanitadi:[object Temporal.PlainDate]. - Resurslar. Fayl, baza ulanishi, qulf kabi obyektlar
Symbol.disposeni yozadi —usingular bilan ishlaydi (using). - Intervyu. "Obyektni
for...ofbilan aylanadigan qiling", "Symbol.toPrimitivenima?", "nega{}iterable emas?" — tajribali (middle) dasturchi lavozimi intervyusida beriladigan savollar.
Xulosa
- Well-known symbols — tilning o'zi yaratgan symbol'lar (
Symbol.iterator,Symbol.toPrimitive…). Til ma'lum amallarda obyektdan shu kalitli metodni so'raydi. Symbol.toPrimitive(hint)—valueOf/toStringdan oldin:number,string,defaultishoraga qarab primitiv qaytaradi; obyekt qaytarsa —TypeError.Symbol.toStringTag—[object Nom]dagi nom; loglarda obyektni tanitadi.Symbol.iterator—for...of, spread, destructuring kaliti; ichki massivning iteratoriga topshirish — eng oddiy yo'l.Symbol.hasInstancevaSymbol.species— tanib oling, lekin o'zingiz kam yozing: yashirin xulq kodni sirli qiladi.
Keyingi dars: Iteratsiya protokoli — Symbol.iterator qaytaradigan iterator va next() → { value, done } kelishuvi: for...of, spread va destructuring ichida aslida nima bo'ladi.
Manbalar
- MDN: "Symbol" — "Well-known symbols" bo'limi; "Symbol.toPrimitive", "Symbol.toStringTag", "Symbol.species" — developer.mozilla.org
- ECMAScript 2025 Language Specification: "Well-Known Symbols", "ToPrimitive", "OrdinaryToPrimitive" — tc39.es/ecma262
- web-features 3.40:
symbol— github.com/web-platform-dx/web-features
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!