Hozirgacha biz quyidagi murakkab maâlumotlar strukturalarini oârgandik:
- Objektlar kalitli toâplamlarni saqlash uchun ishlatiladi.
- Massivlar tartibli toâplamlarni saqlash uchun ishlatiladi.
Ammo bu real hayot uchun yetarli emas. Shuning uchun Map va Set ham mavjud.
Map
Map â bu Object kabi kalitli maâlumotlar toâplamidir. Lekin asosiy farq shundaki, Map har qanday turdagi kalitlarga ruxsat beradi.
Metodlar va xususiyatlar:
new Map()â xaritani yaratadi.map.set(key, value)â kalit boâyicha qiymatni saqlaydi.map.get(key)â kalit boâyicha qiymatni qaytaradi, agarkeyxaritada mavjud boâlmasaundefinedqaytaradi.map.has(key)â agarkeymavjud boâlsatrue, aks holdafalseqaytaradi.map.delete(key)â kalit boâyicha qiymatni oâchiradi.map.clear()â xaritadagi hamma narsani oâchiradi.map.sizeâ hozirgi elementlar sonini qaytaradi.
Misol uchun:
let map = new Map();
map.set('1', 'str1'); // satr kaliti
map.set(1, 'num1'); // raqamli kalit
map.set(true, 'bool1'); // mantiqiy kalit
// oddiy Objektni eslaysizmi? u kalitlarni satrga aylantiradi
// Map turni saqlaydi, shuning uchun bu ikkalasi har xil:
alert( map.get(1) ); // 'num1'
alert( map.get('1') ); // 'str1'
alert( map.size ); // 3
Koârib turganingizdek, objektlardan farqli oâlaroq, kalitlar satrga aylantirilmaydi. Har qanday turdagi kalit mumkin.
map[key] â bu Map dan foydalanishning toâgâri usuli emasGarchi map[key] ham ishlaydi, masalan, biz map[key] = 2 qoâya olamiz, lekin bu map ni oddiy JavaScript objekti sifatida koârib chiqadi, shuning uchun barcha mos cheklovlar keladi (faqat satr/simvol kalitlar va boshqalar).
Shuning uchun biz map metodlaridan foydalanishimiz kerak: set, get va boshqalar.
Map objektlarni ham kalit sifatida ishlatishi mumkin.
Misol uchun:
let john = { name: "John" };
// har bir foydalanuvchi uchun ularning tashrif sonini saqlaymiz
let visitsCountMap = new Map();
// john - xarita uchun kalit
visitsCountMap.set(john, 123);
alert( visitsCountMap.get(john) ); // 123
Objektlarni kalit sifatida ishlatish Map ning eng muhim va diqqatga sazovor xususiyatlaridan biridir. Bu Object uchun amal qilmaydi. Object da satr kalit yaxshi, lekin biz boshqa Object ni Object da kalit sifatida ishlatib boâlmaydi.
Sinab koâraylik:
let john = { name: "John" };
let ben = { name: "Ben" };
let visitsCountObj = {}; // objektdan foydalanishga harakat qilaylik
visitsCountObj[ben] = 234; // ben objektini kalit sifatida ishlatishga harakat qilish
visitsCountObj[john] = 123; // john objektini kalit sifatida ishlatishga harakat qilish, ben objekti almashtiriladi
// Mana nima yozilgan!
alert( visitsCountObj["[object Object]"] ); // 123
visitsCountObj objekt boâlganligi sababli, u barcha Object kalitlarini, masalan yuqoridagi john va ben ni bir xil "[object Object]" satrga aylantiradi. Bu biz xohlagan narsa emas.
Map kalitlarni qanday solishtiradiKalitlarning ekvivalentligini tekshirish uchun Map SameValueZero algoritmidan foydalanadi. Bu qatâiy tenglik === bilan deyarli bir xil, lekin farqi shundaki, NaN NaN ga teng deb hisoblanadi. Shuning uchun NaN ham kalit sifatida ishlatilishi mumkin.
Ushbu algoritm oâzgartirilishi yoki sozlanishi mumkin emas.
Har bir map.set chaqiruvi xaritaning oâzini qaytaradi, shuning uchun biz chaqiruvlarni âzanjirâ qila olamiz:
map.set('1', 'str1')
.set(1, 'num1')
.set(true, 'bool1');
Map ustida iteratsiya
Map ustida sikl uchun 3 ta metod mavjud:
map.keys()â kalitlar uchun iterable qaytaradi,map.values()â qiymatlar uchun iterable qaytaradi,map.entries()â[key, value]yozuvlari uchun iterable qaytaradi, ufor..ofda standart boâyicha ishlatiladi.
Misol uchun:
let recipeMap = new Map([
['cucumber', 500],
['tomatoes', 350],
['onion', 50]
]);
// kalitlar ustida iteratsiya (sabzavotlar)
for (let vegetable of recipeMap.keys()) {
alert(vegetable); // cucumber, tomatoes, onion
}
// qiymatlar ustida iteratsiya (miqdorlar)
for (let amount of recipeMap.values()) {
alert(amount); // 500, 350, 50
}
// [key, value] yozuvlari ustida iteratsiya
for (let entry of recipeMap) { // recipeMap.entries() bilan bir xil
alert(entry); // cucumber,500 (va hokazo)
}
Iteratsiya qiymatlar kiritilgan tartibda boradi. Map bu tartibni saqlaydi, oddiy Object dan farqli oâlaroq.
Bundan tashqari, Map Array ga oâxshash oârnatilgan forEach metodiga ega:
// har bir (key, value) juftlik uchun funktsiyani ishga tushiradi
recipeMap.forEach( (value, key, map) => {
alert(`${key}: ${value}`); // cucumber: 500 va hokazo
});
Object.entries: Objektdan Map
Map yaratilganda, biz uni boshlash uchun kalit/qiymat juftliklari massivini (yoki boshqa iterable) uzatishimiz mumkin:
// [key, value] juftliklari massivi
let map = new Map([
['1', 'str1'],
[1, 'num1'],
[true, 'bool1']
]);
alert( map.get('1') ); // str1
Agar bizda oddiy objekt bor va undan Map yaratmoqchi boâlsak, u holda Object.entries(obj) oârnatilgan metodidan foydalanishimiz mumkin, u objekt uchun aynan shu formatdagi kalit/qiymat juftliklari massivini qaytaradi.
Shunday qilib objektdan xarita yaratishimiz mumkin:
let obj = {
name: "John",
age: 30
};
let map = new Map(Object.entries(obj));
alert( map.get('name') ); // John
Bu erda Object.entries kalit/qiymat juftliklari massivini qaytaradi: [ ["name","John"], ["age", 30] ]. Map ga aynan shu kerak.
Object.fromEntries: Map dan objekt
Biz hozirgina Object.entries(obj) yordamida oddiy objektdan Map yaratishni koârdik.
Teskarisini bajaradigan Object.fromEntries metodi mavjud: [key, value] juftliklari massivini hisobga olgan holda, u ulardan objekt yaratadi:
let prices = Object.fromEntries([
['banana', 1],
['orange', 2],
['meat', 4]
]);
// endi prices = { banana: 1, orange: 2, meat: 4 }
alert(prices.orange); // 2
Biz Map dan oddiy objekt olish uchun Object.fromEntries dan foydalanishimiz mumkin.
Masalan, biz maâlumotlarni Map da saqlaymiz, lekin uni oddiy objekt kutadigan uchinchi tomon kodiga uzatishimiz kerak.
Mana:
let map = new Map();
map.set('banana', 1);
map.set('orange', 2);
map.set('meat', 4);
let obj = Object.fromEntries(map.entries()); // oddiy objekt yarating (*)
// bajarildi!
// obj = { banana: 1, orange: 2, meat: 4 }
alert(obj.orange); // 2
map.entries() chaqiruvi kalit/qiymat juftliklari iterableni qaytaradi, aynan Object.fromEntries uchun toâgâri formatda.
Biz (*) qatorini qisqartira olamiz:
let obj = Object.fromEntries(map); // .entries() ni tashlab qoldiring
Bu bir xil, chunki Object.fromEntries argument sifatida iterable objektni kutadi. Albatta massiv boâlishi shart emas. Va map uchun standart iteratsiya map.entries() bilan bir xil kalit/qiymat juftliklarini qaytaradi. Shunday qilib biz map bilan bir xil kalit/qiymatlarga ega oddiy objektni olamiz.
Set
Set â bu maxsus turdagi toâplam â âqiymatlar toâplamiâ (kalitsiz), bu erda har bir qiymat faqat bir marta paydo boâlishi mumkin.
Uning asosiy metodlari:
new Set(iterable)â toâplamni yaratadi va agariterableobjekt berilgan boâlsa (odatda massiv), undan qiymatlarni toâplamga nusxa koâchiradi.set.add(value)â qiymat qoâshadi, toâplamning oâzini qaytaradi.set.delete(value)â qiymatni oâchiradi, chaqiruv momentidavaluemavjud boâlsatrue, aks holdafalseqaytaradi.set.has(value)â qiymat toâplamda mavjud boâlsatrue, aks holdafalseqaytaradi.set.clear()â toâplamdan hamma narsani oâchiradi.set.sizeâ elementlar soni.
Asosiy xususiyat shundaki, bir xil qiymat bilan set.add(value) ning takrorlangan chaqiruvlari hech narsa qilmaydi. Shuning uchun har bir qiymat Set da faqat bir marta paydo boâladi.
Misol uchun, bizga mehmonlar kelyapti va biz barchani eslab qolishni xohlaymiz. Lekin takrorlangan tashriflar dublikatlar olib kelmasligi kerak. Mehmon faqat bir marta âhisoblanishiâ kerak.
Set aynan shu ish uchun toâgâri:
let set = new Set();
let john = { name: "John" };
let pete = { name: "Pete" };
let mary = { name: "Mary" };
// tashriflar, ba'zi foydalanuvchilar bir necha marta kelishadi
set.add(john);
set.add(pete);
set.add(mary);
set.add(john);
set.add(mary);
// set faqat noyob qiymatlarni saqlaydi
alert( set.size ); // 3
for (let user of set) {
alert(user.name); // John (keyin Pete va Mary)
}
Set ga alternativa foydalanuvchilar massivi boâlishi mumkin va har bir kiritishda arr.find dan foydalanib dublikatlarni tekshiradigan kod. Lekin ishlash ancha yomonroq boâladi, chunki bu metod har bir elementni tekshirib, butun massiv boâylab yuradi. Set noyoblikni tekshirish uchun ichki jihatdan ancha yaxshi optimallashtirilgan.
Set ustida iteratsiya
Biz toâplam ustida for..of yoki forEach dan foydalanib sikl qilishimiz mumkin:
let set = new Set(["oranges", "apples", "bananas"]);
for (let value of set) alert(value);
// forEach bilan bir xil:
set.forEach((value, valueAgain, set) => {
alert(value);
});
Qiziq narsani qayd eting. forEach ga uzatilgan callback funktsiyasi 3 ta argumentga ega: value, keyin bir xil qiymat valueAgain, keyin maqsad objekt. Haqiqatan ham, bir xil qiymat argumentlarda ikki marta paydo boâladi.
Bu Map bilan moslashish uchun, bu erda forEach ga uzatilgan callback uchta argumentga ega. Albatta, biroz gâalati koârinadi. Lekin Map ni Set bilan oson almashtirish va aksincha yordam berishi mumkin.
Map da iteratorlar uchun bir xil metodlar Set da ham qoâllab-quvvatlanadi:
set.keys()â qiymatlar uchun iterable objektni qaytaradi,set.values()âset.keys()bilan bir xil,Mapbilan moslashish uchun,set.entries()â[value, value]yozuvlari uchun iterable objektni qaytaradi,Mapbilan moslashish uchun mavjud.
Xulosa
Map â kalitli qiymatlar toâplami.
Metodlar va xususiyatlar:
new Map([iterable])â xaritani yaratadi, boshlash uchun ixtiyoriyiterable(masalan, massiv)[key,value]juftliklari bilan.map.set(key, value)â kalit boâyicha qiymatni saqlaydi, xaritaning oâzini qaytaradi.map.get(key)â kalit boâyicha qiymatni qaytaradi, agarkeyxaritada mavjud boâlmasaundefined.map.has(key)â agarkeymavjud boâlsatrue, aks holdafalseqaytaradi.map.delete(key)â kalit boâyicha qiymatni oâchiradi, chaqiruv momentidakeymavjud boâlsatrue, aks holdafalseqaytaradi.map.clear()â xaritadagi hamma narsani oâchiradi.map.sizeâ hozirgi elementlar sonini qaytaradi.
Oddiy Object dan farqlari:
- Har qanday kalitlar, objektlar kalit boâlishi mumkin.
- Qoâshimcha qulay metodlar,
sizexususiyati.
Set â noyob qiymatlar toâplami.
Metodlar va xususiyatlar:
new Set([iterable])â toâplamni yaratadi, boshlash uchun ixtiyoriyiterable(masalan, massiv) qiymatlar bilan.set.add(value)â qiymat qoâshadi (valuemavjud boâlsa hech narsa qilmaydi), toâplamning oâzini qaytaradi.set.delete(value)â qiymatni oâchiradi, chaqiruv momentidavaluemavjud boâlsatrue, aks holdafalseqaytaradi.set.has(value)â qiymat toâplamda mavjud boâlsatrue, aks holdafalseqaytaradi.set.clear()â toâplamdan hamma narsani oâchiradi.set.sizeâ elementlar soni.
Map va Set ustida iteratsiya har doim kiritish tartibida boâladi, shuning uchun biz bu toâplamlar tartibsiz deb ayta olmaymiz, lekin elementlarni qayta tartiblay olmaymiz yoki raqami boâyicha toâgâridan-toâgâri element olishimiz mumkin emas.
Izohlar
<code>yorlig'ini ishlating, bir nechta satrlar uchun - ularni<pre>yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepenâ¦)