Mundarija (34)
- Bu darsda
- 1. Nega bu kerak?
- 2. getElementById — id bo'yicha
- 3. querySelector — istalgan CSS selektor bilan
- 3.1 Birinchi mos element
- 3.2 Topilmasa — null, va undan himoya
- 3.3 JavaScript uchun qanday selektor yaxshi?
- 4. querySelectorAll — hammasi
- 4.1 NodeList ro'yxati
- 4.2 NodeList — massiv emas
- 5. Element ichida qidirish
- 6. closest — yuqoriga qarab qidirish
- 6.1 Amaliy holat: tugmadan kartaga
- 7. matches — "shu selektorga mosmi?"
- 8. Jonli va statik ro'yxatlar
- 8.1 Ikki xil ro'yxat
- 8.2 Jonli ro'yxat va sikl — klassik tuzoq
- 8.3 Eski to'plamlar va id nomidagi "global o'zgaruvchi"
- 9. Qaysi metodni tanlash kerak?
- 10. DevTools yordamchilari: $ va $$
- 11. Ko'p uchraydigan xatolar
- 11.1 Noto'g'ri selektor
- 11.2 getElementById ga # yozish
- 11.3 Bitta kutib, ro'yxat olish (va aksincha)
- 11.4 Skript elementdan oldin
- 11.5 Xato yo'q, lekin "boshqa" element topildi
- 12. Mashqlar
- 1-mashq (oson): Topib chiqaring
- 2-mashq (o'rta): Buyurtma summasi
- 3-mashq (qiyin): Achchiq taomlar
- 4-mashq: Portfolio qadami — menyuni topish
- 13. Real ishda
- Xulosa
- Manbalar
JavaScript'da elementlarni tanlash: querySelector, getElementById, closest va matches
Qisqacha: Sahifadagi elementni JavaScript'da CSS selektor bilan topasiz. Birinchi mos element —
document.querySelector(".narx")(yo'q bo'lsanull), hammasi —querySelectorAll,idbo'yicha —getElementById("menyu"). Yuqoriga qarab eng yaqin otaniclosesttopadi, "shu selektorga mosmi?" degan savolgamatchesjavob beradi. Eslab qoling:querySelectorAllro'yxati statik,childrenvagetElementsBy...esa jonli.
Bu darsda
getElementById,querySelectorvaquerySelectorAllbilan istalgan elementni topa olasiz.- CSS darslaridagi selektorlarni JavaScript'da qayta ishlatasiz.
closestbilan elementning "oilasini" topib,matchesbilan uni tekshira olasiz.- Statik
NodeListva jonliHTMLCollectionfarqini va undan kelib chiqadigan tuzoqni bilasiz. nullva noto'g'ri selektor xatolarini tez topib tuzata olasiz.
Oldin bilishingiz kerak: DOM daraxti va tugun turlari, Asosiy selektorlar va kombinatorlar, Atribut selektorlari, ?? va optional chaining.
1. Nega bu kerak?
Ofitsiant Otabekka Jasur aka aytdi: "Doskadagi manti narxini 30 000 deb yangilab qo'y". Otabek avval menyu doskasida manti qatorini topadi, keyin narxni o'chirib yozadi. Topmasdan yozib bo'lmaydi.
JavaScript ham shunday. Sahifada matnni almashtirish, rangni o'zgartirish, tugmani yashirish — har ish bitta savoldan boshlanadi: qaysi element? O'tgan darsda DOM daraxti qanday tuzilganini ko'rdingiz. Endi undan kerakli tugunni tez va aniq topishni o'rganamiz.
Yaxshi xabar: siz buni allaqachon bilasiz. CSS'da .narx, #menyu li, a[href^="https://"] deb yozgansiz — bu selektorlar (selectors), ya'ni "qaysi elementlar" degan savolning javobi. Asosiy selektorlar darsida va'da qilingandek, JavaScript elementni aynan shu selektorlar bilan qidiradi. CSS'da selektor elementni bezash uchun edi, JavaScript'da — topish uchun.
Dars uch savolga javob beradi: bitta elementni qanday topish, ko'p elementni qanday topish va topilgan elementdan uning "qarindoshlari"ga qanday o'tish. Oxirida qaysi usul qachon qulayligini bitta diagrammada jamlaymiz.
Bu darsdagi misollar bitta «Bahor» menyusida:
<ul id="menyu">
<li class="taom-karta">Osh <span class="narx">35 000</span></li>
<li class="taom-karta yangi">
Manti <span class="narx">30 000</span>
</li>
<li class="taom-karta">Lag'mon <span class="narx">28 000</span></li>
</ul>2. getElementById — id bo'yicha
Eng eski va eng sodda usul. id sahifada takrorlanmas bo'lgani uchun natija — bitta element yoki null:
<ul id="menyu">
<li class="taom-karta">Osh <span class="narx">35 000</span></li>
<li class="taom-karta yangi">
Manti <span class="narx">30 000</span>
</li>
</ul>
<script>
const menyu = document.getElementById("menyu");
console.log(menyu);
console.log(document.getElementById("bron"));
console.log(document.getElementById("#menyu"));
</script>Konsolda:
<ul id="menyu">…</ul>
null
null- Birinchi qator — topildi.
brondeganidyo'q —null. Xato emas, "topilmadi" degan javob (undefinedvanulldarsida va'da qilingan holat shu).- Uchinchisi — eng ko'p uchraydigan xato:
getElementByIdga#yozilmaydi. Unga selektor emas,idning o'zi beriladi.#menyudeganidyo'q —null.
Metod faqat document da bor: menyu.getElementById(...) deb element ichida qidirib bo'lmaydi.
Sahifada bir xil id ikki marta yozilgan bo'lsa-chi? HTML qoidasi buzilgan, lekin brauzer xato bermaydi: getElementById birinchisini qaytaradi, ikkinchisi esa JavaScript'dan "yashirinib" qoladi. Bunday xatoni HTML validatori darhol ushlaydi — npm run check shuning uchun ham foydali.
Tekshirib ko'ring:
document.getElementById("Menyu")— sahifadaid="menyu"bo'lsa, nima qaytaradi?
Javob
null. id katta-kichik harfni farqlaydi: Menyu va menyu — ikki xil nom. JavaScript'dagi o'zgaruvchi nomlari kabi.
3. querySelector — istalgan CSS selektor bilan
3.1 Birinchi mos element
querySelector istalgan CSS selektorni qabul qiladi va daraxtni yuqoridan pastga ko'rib chiqib, birinchi mos elementni qaytaradi:
<ul id="menyu">
<li class="taom-karta">Osh <span class="narx">35 000</span></li>
<li class="taom-karta yangi">
Manti <span class="narx">30 000</span>
</li>
<li class="taom-karta">Lag'mon <span class="narx">28 000</span></li>
</ul>
<script>
console.log(document.querySelector(".narx"));
console.log(document.querySelector(".yangi .narx"));
console.log(document.querySelector("li:last-child"));
console.log(document.querySelector("#menyu"));
</script>Konsolda:
<span class="narx">35 000</span>
<span class="narx">30 000</span>
<li class="taom-karta">…</li>
<ul id="menyu">…</ul>.narxuchta, lekin qaytgani birinchisi — osh narxi..yangi .narx— kombinator: "yangiclass'li element ichidagi narx" (Kombinatorlar).li:last-child— Tuzilma pseudo-klasslari darsidagi selektor. Lag'mon qatori.#menyu—getElementById("menyu")bilan bir xil natija. Bu yerda#kerak, chunki bu selektor.
Hayotdan o'xshatish: kutubxonachiga "qizil muqovali birinchi kitobni bering" deysiz. U javonlarni chapdan o'ngga ko'rib chiqadi va birinchi qizil kitobni olib keladi. Qolgan qizil kitoblarni ham olib kelmaydi.
3.2 Topilmasa — null, va undan himoya
Selektorga hech narsa mos kelmasa, null qaytadi. Keyingi qatorda uning textContent ini o'qisangiz — o'tgan darslardagi tanish xato. Element bo'lmasligi mumkin bo'lgan joyda ikki yo'l bor:
<p class="narx">35 000</p>
<script>
const aksiya = document.querySelector(".aksiya");
if (aksiya !== null) {
console.log(aksiya.textContent);
} else {
console.log("Bugun aksiya yo'q");
}
console.log(document.querySelector(".aksiya")?.textContent);
</script>Konsolda:
Bugun aksiya yo'q
undefinedBirinchisi — oddiy if. Ikkinchisi — optional chaining ?.: chap tomoni null bo'lsa, xato o'rniga undefined qaytaradi.
Qaysi biri qachon? Element albatta bo'lishi kerak bo'lsa (sahifaning asosiy tugmasi) — ?. qo'ymang. Xato darhol chiqsin, siz uni ko'rib tuzatasiz. Element bo'lmasligi mumkin bo'lsa (aksiya faqat juma kuni chiqadi) — if yoki ?..
Tekshirib ko'ring: Menyuda uchta
.narxbor.document.querySelector(".narx").textContentnima qaytaradi?
Javob
"35 000" — faqat birinchi narx. querySelector doim bitta element qaytaradi. Hammasi kerak bo'lsa — querySelectorAll.
3.3 JavaScript uchun qanday selektor yaxshi?
CSS'da selektor faqat ko'rinishga ta'sir qiladi: xato bo'lsa, rang noto'g'ri chiqadi. JavaScript'da esa selektor buzilsa, tugma umuman ishlamay qoladi. Shuning uchun JavaScript selektori mustahkam bo'lishi kerak — dizayn o'zgarganda buzilmasin.
| Selektor | Baho | Nega |
|---|---|---|
#menyu |
yaxshi | id takrorlanmas, kamdan-kam o'zgaradi |
nav[aria-label="Asosiy menyu"] |
yaxshi | Ma'noga bog'langan, qulaylik uchun ham kerak |
.taom-karta |
odatda yaxshi | Ma'noli nom, ko'rinishga emas |
div > div:nth-child(3) span |
mo'rt | Bitta div qo'shilsa — boshqa element topiladi |
Qoida: elementni uning ma'nosi bo'yicha toping, sahifadagi joyi bo'yicha emas. Nodira dizaynni yangilab, kartalarni boshqa tartibda joylashi mumkin. .taom-karta baribir o'sha kartani topadi, div:nth-child(3) esa boshqasini.
Keyinroq JavaScript uchun maxsus atributlar ham ko'rasiz: data-* (Atributlar va dataset). Ular dizaynchi tegmaydigan, faqat dastur uchun nom — CSS class'larini o'zgartirish JavaScript'ni buzmaydi.
4. querySelectorAll — hammasi
4.1 NodeList ro'yxati
querySelectorAll mos kelgan barcha elementlarni NodeList deb ataladigan ro'yxatda qaytaradi:
<ul id="menyu">
<li class="taom-karta">Osh <span class="narx">35 000</span></li>
<li class="taom-karta yangi">
Manti <span class="narx">30 000</span>
</li>
<li class="taom-karta">Lag'mon <span class="narx">28 000</span></li>
</ul>
<script>
const kartalar = document.querySelectorAll(".taom-karta");
console.log(kartalar);
console.log(kartalar.length);
console.log(kartalar[1]);
for (const narx of document.querySelectorAll(".narx")) {
console.log(narx.textContent);
}
console.log(document.querySelectorAll(".aksiya"));
</script>Konsolda:
NodeList(3) [li.taom-karta, li.taom-karta.yangi, li.taom-karta]
3
<li class="taom-karta yangi">…</li>
35 000
30 000
28 000
NodeList(0) []NodeList massivga juda o'xshaydi:
.length— nechta topildi;[1]— indeks bo'yicha element;for...ofvaforEachbilan aylanish mumkin (Massiv bo'ylab yurish).
Muhim farq: hech narsa topilmasa, null emas, bo'sh ro'yxat NodeList(0) [] qaytadi. Bo'sh ro'yxatni aylansangiz, sikl bir marta ham ishlamaydi — xato ham chiqmaydi.
4.2 NodeList — massiv emas
NodeList da forEach bor, lekin massivning ko'p metodlari yo'q. Ularni 10-qismda o'rganasiz, lekin farqni bugun bilib qo'ying. Haqiqiy massiv kerak bo'lsa — spread bilan aylantiring:
<a href="https://example.com/bron">Bron</a>
<a href="#menyu">Menyu</a>
<script>
const havolalar = document.querySelectorAll("a");
console.log(Array.isArray(havolalar), havolalar);
const massiv = [...havolalar];
console.log(Array.isArray(massiv), massiv);
</script>Konsolda:
false NodeList(2) [a, a]
true (2) [a, a]Ro'yxatdan faqat ba'zilarini tanlash kerak bo'lsa, bugungi bilim bilan — for...of va if. Masalan, faqat yangi taomlar — buni «matches» bo'limida ko'ramiz.
Tekshirib ko'ring:
document.querySelectorAll("li")[5]— menyuda faqat uchtalibo'lsa, nima qaytaradi?
Javob
undefined — xuddi massivda mavjud bo'lmagan indeks kabi. Xato chiqmaydi, lekin keyingi .textContent da Cannot read properties of undefined xatosi chiqadi. E'tibor bering: bu safar null emas, undefined.
5. Element ichida qidirish
querySelector va querySelectorAll faqat document da emas, har qanday elementda bor. Shunda qidiruv faqat shu elementning ichida bo'ladi:
<article class="taom-karta">
<h2>Osh</h2>
<span class="narx">35 000</span>
</article>
<article class="taom-karta">
<h2>Manti</h2>
<span class="narx">30 000</span>
</article>
<script>
const ikkinchi = document.querySelectorAll(".taom-karta")[1];
console.log(ikkinchi.querySelector("h2").textContent);
console.log(ikkinchi.querySelector(".narx").textContent);
</script>Konsolda:
Manti
30 000Bu juda ko'p ishlatiladi: avval "karta"ni topasiz, keyin uning ichidan kerakli bo'laklarni olasiz. Butun sahifadan .narx ni qidirsangiz, osh narxi chiqardi.
Bitta nozik tuzoq bor. Selektorning o'zi butun sahifaga nisbatan tekshiriladi, faqat natija element ichidan olinadi:
<ul id="menyu">
<li>Osh</li>
<li>Manti</li>
</ul>
<script>
const menyu = document.getElementById("menyu");
console.log(menyu.querySelectorAll("body li").length);
console.log(menyu.querySelectorAll(":scope > li").length);
</script>Konsolda:
2
2Birinchi qatorga qarang: menyu ning ichida body yo'q, lekin body li baribir ikkita topdi. Brauzer har li ni tekshirdi: "uning ota-bobolari orasida body bormi?" — bor (menyudan tashqarida bo'lsa ham). Selektor "menyu ichidagi body ichidagi li" emas, "butun sahifada body ichida turgan va menyuning ichidagi li" deb o'qiladi.
:scope — "aynan shu element" degan maxsus pseudo-klass. :scope > li — "menyuning bevosita bolalari bo'lgan li lar". Element ichida qidirishda selektorni elementning o'ziga bog'lash kerak bo'lsa — :scope bilan boshlang.
Tekshirib ko'ring: Sahifada ikkita karta bor, ikkalasida ham
h2.ikkinchi— ikkinchi karta.document.querySelector("h2")vaikkinchi.querySelector("h2")bir xil elementni beradimi?
Javob
Yo'q. document.querySelector("h2") butun sahifadan qidiradi va birinchi kartaning sarlavhasini topadi. ikkinchi.querySelector("h2") esa faqat ikkinchi kartaning ichidan qidiradi va uning o'z sarlavhasini beradi. Qidiruv qayerdan boshlansa, natija o'sha joyga bog'liq.
6. closest — yuqoriga qarab qidirish
querySelector pastga (ichkariga) qidiradi. Ba'zan teskari kerak bo'ladi: sizda narx span i bor, siz uning kartasini topmoqchisiz. closest(selektor) elementning o'zidan boshlab otasi, bobosi — tobora yuqoriga qarab boradi va birinchi mos kelganini qaytaradi:
<ul id="menyu">
<li class="taom-karta">Osh <span class="narx">35 000</span></li>
<li class="taom-karta yangi">
Manti <span class="narx">30 000</span>
</li>
</ul>
<script>
const narx = document.querySelector(".yangi .narx");
console.log(narx.closest(".taom-karta"));
console.log(narx.closest("ul"));
console.log(narx.closest("span"));
console.log(narx.closest("form"));
</script>Konsolda:
<li class="taom-karta yangi">…</li>
<ul id="menyu">…</ul>
<span class="narx">30 000</span>
null.taom-karta— eng yaqin ota-karta, manti qatori.ul— ikki qadam yuqoridagi menyu.span— elementning o'zi.closestqidiruvni o'zidan boshlaydi.form— yuqorida forma yo'q,null.
Hayotdan o'xshatish: siz katta bozordasiz va "eng yaqin chiqish qayerda?" deb so'raysiz. Siz turgan joyning o'zi chiqish bo'lsa — javob "shu yer". Bo'lmasa, yo'lak, keyin qator, keyin bo'lim bo'ylab chiqishni qidirasiz.
6.1 Amaliy holat: tugmadan kartaga
Har taom kartasida "Savatga" tugmasi bor. Tugma bosilganda qaysi taom tanlanganini bilish kerak. Tugmaning o'zida taom nomi yo'q — u kartada. Yo'l: tugmadan closest bilan kartaga chiqish, keyin karta ichidan nomni olish. Hozircha bosishsiz, ikkinchi tugmani qo'lda tanlab ko'ramiz:
<article class="taom-karta">
<h2 class="taom-nomi">Osh</h2>
<button type="button">Savatga</button>
</article>
<article class="taom-karta">
<h2 class="taom-nomi">Manti</h2>
<button type="button">Savatga</button>
</article>
<script>
const tugma = document.querySelectorAll("button")[1];
const karta = tugma.closest(".taom-karta");
const nomi = karta.querySelector(".taom-nomi").textContent;
console.log(`Savatga qo'shildi: ${nomi}`);
</script>Konsolda:
Savatga qo'shildi: MantiKartalar 2 ta emas, 200 ta bo'lsa ham kod o'zgarmaydi: har tugma o'z kartasini topadi. Tugmani bosishga javob berishni addEventListener asoslari darsida qo'shamiz.
closest hodisalar darslarida eng ko'p ishlatiladigan metodlardan biriga aylanadi: foydalanuvchi kartaning qayeriga bosganini bilasiz, closest(".taom-karta") bilan esa kartaning o'zini topasiz.
7. matches — "shu selektorga mosmi?"
matches(selektor) elementni qidirmaydi — uni tekshiradi va true yoki false qaytaradi:
<ul id="menyu">
<li class="taom-karta">Osh</li>
<li class="taom-karta yangi">Manti</li>
<li class="taom-karta yangi">Lag'mon</li>
</ul>
<script>
const kartalar = document.querySelectorAll(".taom-karta");
console.log(kartalar[0].matches(".yangi"));
console.log(kartalar[1].matches("#menyu > .yangi"));
let yangilar = 0;
for (const karta of kartalar) {
if (karta.matches(".yangi")) {
yangilar++;
console.log("Yangi:", karta.textContent);
}
}
console.log(`Jami yangi taom: ${yangilar}`);
</script>Konsolda:
false
true
Yangi: Manti
Yangi: Lag'mon
Jami yangi taom: 2matches istalgan murakkab selektorni tushunadi, shuning uchun nodeName === "LI" kabi qo'lda tekshiruvlardan ishonchliroq (DOM daraxti darsidagi katta harf tuzog'ini eslang).
Tekshirib ko'ring:
closestvamatchesfarqi nima?el.closest(".x") === elqachontruebo'ladi?
Javob
matches faqat elementning o'zini tekshiradi va true/false qaytaradi. closest esa o'zidan yuqoriga qarab qidiradi va element (yoki null) qaytaradi. el.closest(".x") === el — element o'zi .x ga mos bo'lsa, ya'ni el.matches(".x") true bo'lsa.
8. Jonli va statik ro'yxatlar
8.1 Ikki xil ro'yxat
Elementlar to'plamini qaytaradigan eski metodlar ham bor:
| Metod | Nima qaytaradi | Holati |
|---|---|---|
querySelectorAll(".x") |
NodeList |
statik |
getElementsByClassName("x") |
HTMLCollection |
jonli |
getElementsByTagName("li") |
HTMLCollection |
jonli |
element.children |
HTMLCollection |
jonli |
Statik (static) ro'yxat — chaqirilgan paytdagi "surat". Keyin DOM o'zgarsa ham, ro'yxat o'zgarmaydi. Jonli (live) ro'yxat esa DOM'ga ulangan: element qo'shilsa yoki o'chirilsa, ro'yxat ham o'zi o'zgaradi.
Farqni ko'rish uchun bitta elementni o'chiramiz. element.remove() — elementni DOM'dan olib tashlaydi, uni Element yaratish va o'chirish darsida to'liq o'rganamiz:
<ul id="menyu">
<li class="taom-karta">Osh</li>
<li class="taom-karta">Manti</li>
<li class="taom-karta">Lag'mon</li>
</ul>
<script>
const surat = document.querySelectorAll(".taom-karta");
const jonli = document.getElementsByClassName("taom-karta");
console.log(surat.length, jonli.length);
surat[2].remove();
console.log(surat.length, jonli.length);
console.log(jonli);
</script>Konsolda:
3 3
3 2
HTMLCollection(2) [li.taom-karta, li.taom-karta]Lag'mon sahifadan o'chdi. surat hali ham "3" deydi — u eski surat, uchinchi elementi endi sahifada yo'q. jonli esa o'zi 2 ga tushdi.
Hayotdan o'xshatish: querySelectorAll — zalning ertalabki fotosurati. HTMLCollection — zaldagi jonli kamera: mehmon chiqib ketsa, ekrandan ham yo'qoladi.
Bitta istisno: childNodes ham NodeList, lekin u jonli. Statiklik NodeList turiga emas, uni querySelectorAll qaytarganiga bog'liq.
8.2 Jonli ro'yxat va sikl — klassik tuzoq
Jonli ro'yxatni aylanayotib undan element o'chirsangiz, ro'yxat oyog'ingiz ostida qisqaradi:
<ul>
<li class="eski">1</li>
<li class="eski">2</li>
<li class="eski">3</li>
<li class="eski">4</li>
</ul>
<script>
const eskilar = document.getElementsByClassName("eski");
for (let i = 0; i < eskilar.length; i++) {
eskilar[i].remove();
}
console.log(document.querySelectorAll("li").length);
</script>Konsolda:
2To'rttasini o'chirmoqchi edik — ikkitasi qoldi. Nega? i = 0 da birinchi li o'chdi, ro'yxat siljidi: endi "2" nolinchi o'rinda. i = 1 da biz "3" ni o'chirdik — "2" tashlab ketildi. Xato xabari yo'q — natija shunchaki noto'g'ri.
Tuzatish: statik ro'yxat bilan ishlang — document.querySelectorAll(".eski"). U surat, o'chirish uni siljitmaydi. Yangi kodda deyarli doim querySelectorAll ishlatiladi — tuzoqning o'zi kamroq.
Tekshirib ko'ring: Yuqoridagi tuzoqli kodda
getElementsByClassNameniquerySelectorAll(".eski")ga almashtiring ("Tahrirlab ko'rish"). Konsolda nima chiqadi va nega?
Javob
0 — hamma li o'chdi. Statik NodeList sikl davomida o'zgarmaydi: to'rtta element bor edi, sikl to'rt marta aylanib, har birini o'chirdi.
8.3 Eski to'plamlar va id nomidagi "global o'zgaruvchi"
Eski kodda yana bir necha tanlash usulini uchratasiz. Ular ishlaydi, lekin yangi kodda kam yoziladi:
<ul id="menyu"><li>Osh</li></ul>
<form name="bron" action="https://example.com/bron" method="post">
<input name="ism" aria-label="Ism">
</form>
<a href="https://example.com/menyu">Menyu</a>
<script>
console.log(document.forms.length, document.links.length);
console.log(document.getElementsByName("ism"));
console.log(menyu);
console.log(window.menyu === document.getElementById("menyu"));
</script>Konsolda:
1 1
NodeList(1) [input]
<ul id="menyu">…</ul>
truedocument.forms,document.links,document.images— sahifadagi barcha formalar, havolalar, rasmlar. Formalarni forma darslarida o'rganamiz: u yerda formaniquerySelectorbilan topib, maydonlariniforma.elementsorqali olamiz.getElementsByName("ism")—nameatributi bo'yicha.- Uchinchi qator g'alati: biz
menyudegan o'zgaruvchi e'lon qilmadik, lekin u bor! Brauzeridli har elementniwindowga shu nom bilan qo'yib qo'yadi.
Bu "sovg'a"ga hech qachon tayanmang. id ni o'zgartirsangiz yoki shu nomli o'zgaruvchi e'lon qilsangiz, kod jimgina buziladi. Kod o'quvchisi menyu qayerdan kelganini ham tushunmaydi. Doim aniq yozing: const menyu = document.getElementById("menyu");.
9. Qaysi metodni tanlash kerak?
Diagrammani yuqoridan o'qing — har savolga "ha" yoki "yo'q":
flowchart TD
S{"Nechta element kerak?"}
S -->|bitta| B{"Yuqoriga qarab, ota-karta?"}
S -->|hammasi| A["querySelectorAll — NodeList"]
B -->|ha| C["closest"]
B -->|yo'q| D{"Faqat id bo'yicha?"}
D -->|ha| E["getElementById yoki querySelector"]
D -->|yo'q| F["querySelector"]
T{"Topmasdan, faqat tekshirish?"}
T --> M["matches — true / false"]Amaliy qoida: kundalik ishda querySelector, querySelectorAll va closest yetadi. getElementById — tez va aniq, id bo'lsa bemalol. getElementsBy... — asosan eski kodda uchratasiz.
Tezlik haqida: farq millisekundning mingdan biriga teng, ko'p hollarda sezilmaydi. Muhimi boshqa: bir elementni sikl ichida qayta-qayta qidirmang — bir marta topib, const ga saqlang.
// ❌ har aylanishda butun sahifa qayta qidiriladi
for (const nom of ["Osh", "Manti", "Lag'mon"]) {
document.querySelector("#menyu").append(nom);
}
// ✅ bir marta topiladi, keyin tayyor o'zgaruvchi ishlatiladi
const menyu = document.querySelector("#menyu");
for (const nom of ["Osh", "Manti", "Lag'mon"]) {
menyu.append(nom);
}append — elementga matn yoki element qo'shadi, uni Element yaratish, joylash va o'chirish darsida o'rganamiz; bu yerda faqat tanlash qayerda turganiga qarang. Ikkinchi variant ham tezroq, ham o'qishga qulayroq: menyu nomi kodning qolgan qismida nima bilan ishlayotganimizni aytib turadi.
10. DevTools yordamchilari: $ va $$
Kompyuterdagi DevTools konsolida ikki qisqartma bor (DOM daraxti darsidagi $0 ning qarindoshlari):
$(".narx"); // document.querySelector(".narx") bilan bir xil
$$(".narx"); // querySelectorAll, lekin natija — haqiqiy massivSelektorni kodga yozishdan oldin konsolda $$ bilan sinash qulay: nechta topildi, aynan o'shalarmi?
Lekin ular faqat DevTools konsolining yordamchisi. Kodingizda yoki jonli oynada ishlatsangiz:
<p class="narx">35 000</p>
<script>
const narx = $(".narx");
</script>Konsolda:
Uncaught ReferenceError: $ is not definedTarjimasi: "$ aniqlanmagan". Eski kodda $(...) ni ko'p uchratasiz — bu jQuery degan kutubxona, u alohida ulanadi. Brauzerning o'zida $ yo'q.
11. Ko'p uchraydigan xatolar
11.1 Noto'g'ri selektor
id raqam bilan boshlangan bo'lsa (HTML'da bunga ruxsat bor), CSS selektor sifatida u yaroqsiz:
<p id="1-taom">Osh</p>
<script>
console.log(document.getElementById("1-taom"));
document.querySelector("#1-taom");
</script>Konsolda:
<p id="1-taom">Osh</p>
Uncaught SyntaxError: Failed to execute 'querySelector' on 'Document': '#1-taom' is not a valid selector.Tarjimasi: "Document da querySelector ni bajarib bo'lmadi: '#1-taom' — yaroqli selektor emas". null dan farqli, bu — haqiqiy xato: skript shu yerda to'xtaydi. Yopilmagan qavs (li:not(.yangi), ortiqcha belgi ham shu xatoni beradi. Tuzatish: id ni harf bilan boshlang (taom-1) yoki getElementById ishlating — u selektor emas, shuning uchun bunday cheklovi yo'q.
11.2 getElementById ga # yozish
getElementById("#menyu") → null. # faqat selektorda: querySelector("#menyu").
11.3 Bitta kutib, ro'yxat olish (va aksincha)
querySelectorAll(".narx").textContent → undefined: ro'yxatning textContent i yo'q, u har elementda. querySelector(".narx") esa faqat birinchisini beradi. Qaysi biri kerakligini oldindan hal qiling: bitta — querySelector, hammasi — querySelectorAll + sikl.
11.4 Skript elementdan oldin
Hamma tanlash metodlari faqat DOM'da bor elementni topadi. Skript defer siz <head> da bo'lsa — hammasi null yoki bo'sh ro'yxat (Brauzer muhiti darsidagi tuzoq).
11.5 Xato yo'q, lekin "boshqa" element topildi
Eng ayyor xato — kod ishlaydi, lekin noto'g'ri elementni o'zgartiradi. Masalan, querySelector("h2") menyu kartasidagi sarlavhani topadi deb o'ylaysiz, lekin sahifa tepasida aksiya bloki bor va uning ichida ham h2. Birinchi topilgani — aksiya sarlavhasi.
Bunday xato faqat sahifaga yangi blok qo'shilganda paydo bo'ladi — kecha ishlagan kod bugun "o'zi" buziladi. Ikki odat yordam beradi:
- Selektorni aniqroq yozing:
h2emas,#menyu .taom-nomi. - Kerakli joy ichida qidiring: avval kartani yoki bo'limni toping, keyin uning ichidan.
Shubha bo'lsa, natijani konsolga chiqarib qarang: console.log(element) qaysi element topilganini darhol ko'rsatadi. DevTools konsolida bu elementning ustiga sichqonchani olib borsangiz, sahifada u yoritiladi.
12. Mashqlar
1-mashq (oson): Topib chiqaring
Quyidagi oynada konsolga chiqaring: (1) id="bron" li elementning matnini; (2) birinchi .narx ni; (3) nechta li borligini.
<ul id="menyu">
<li>Osh <span class="narx">35 000</span></li>
<li>Ko'k choy <span class="narx">5 000</span></li>
</ul>
<a id="bron" href="https://example.com/bron">Stol band qilish</a>
<script>
// shu yerga yozing
</script>Yechim
<ul id="menyu">
<li>Osh <span class="narx">35 000</span></li>
<li>Ko'k choy <span class="narx">5 000</span></li>
</ul>
<a id="bron" href="https://example.com/bron">Stol band qilish</a>
<script>
console.log(document.getElementById("bron").textContent);
console.log(document.querySelector(".narx"));
console.log(document.querySelectorAll("li").length);
</script>Konsolda:
Stol band qilish
<span class="narx">35 000</span>
22-mashq (o'rta): Buyurtma summasi
Mehmon buyurtmasi — #buyurtma ro'yxati. Har .narx ni o'qib, umumiy summani hisoblang: Jami: 68000 so'm.
Ishora: "35 000" — satr va ichida bo'sh joy. Avval replaceAll(" ", "") bilan bo'sh joyni olib tashlang (Matnni o'zgartirish), keyin Number() bilan songa aylantiring (Matn ↔ son). Qidiruvni #buyurtma ichida qiling — sahifada boshqa narxlar ham bor.
<p>Bugungi aksiya: <span class="narx">25 000</span></p>
<ul id="buyurtma">
<li>Osh <span class="narx">35 000</span></li>
<li>Lag'mon <span class="narx">28 000</span></li>
<li>Ko'k choy <span class="narx">5 000</span></li>
</ul>
<script>
// shu yerga yozing
</script>Yechim
<p>Bugungi aksiya: <span class="narx">25 000</span></p>
<ul id="buyurtma">
<li>Osh <span class="narx">35 000</span></li>
<li>Lag'mon <span class="narx">28 000</span></li>
<li>Ko'k choy <span class="narx">5 000</span></li>
</ul>
<script>
const buyurtma = document.getElementById("buyurtma");
let jami = 0;
for (const narx of buyurtma.querySelectorAll(".narx")) {
jami += Number(narx.textContent.replaceAll(" ", ""));
}
console.log(`Jami: ${jami} so'm`);
</script>Konsolda:
Jami: 68000 so'mdocument.querySelectorAll(".narx") yozsangiz, aksiya narxi ham qo'shilib, 93000 chiqardi. Element ichida qidirish aynan shunday xatolardan saqlaydi. Pulni chiroyli yozish (68 000) — 08-qismdagi somYoz funksiyasi bilan.
3-mashq (qiyin): Achchiq taomlar
Har .narx uchun uning kartasini closest bilan toping. Karta .achchiq bo'lsa (matches), konsolga taom nomini (.taom-nomi) chiqaring. Oxirida achchiq taomlar sonini chiqaring. Kutilgan natija: Achchiq: Lag'mon, Achchiq: Shashlik, Jami: 2.
<ul id="menyu">
<li class="taom-karta">
<span class="taom-nomi">Osh</span>
<span class="narx">35 000</span>
</li>
<li class="taom-karta achchiq">
<span class="taom-nomi">Lag'mon</span>
<span class="narx">28 000</span>
</li>
<li class="taom-karta achchiq">
<span class="taom-nomi">Shashlik</span>
<span class="narx">18 000</span>
</li>
</ul>
<script>
// shu yerga yozing
</script>Yechim
<ul id="menyu">
<li class="taom-karta">
<span class="taom-nomi">Osh</span>
<span class="narx">35 000</span>
</li>
<li class="taom-karta achchiq">
<span class="taom-nomi">Lag'mon</span>
<span class="narx">28 000</span>
</li>
<li class="taom-karta achchiq">
<span class="taom-nomi">Shashlik</span>
<span class="narx">18 000</span>
</li>
</ul>
<script>
let soni = 0;
for (const narx of document.querySelectorAll(".narx")) {
const karta = narx.closest(".taom-karta");
if (karta.matches(".achchiq")) {
const nomi = karta.querySelector(".taom-nomi").textContent;
console.log(`Achchiq: ${nomi}`);
soni++;
}
}
console.log(`Jami: ${soni}`);
</script>Konsolda:
Achchiq: Lag'mon
Achchiq: Shashlik
Jami: 2Uch harakat birga: closest — yuqoriga (narxdan kartaga), matches — tekshirish, querySelector — karta ichida pastga (nomga). Hodisalar darslarida aynan shu "yuqoriga chiq — tekshir — pastga tush" qolipi har kuni kerak bo'ladi. Shashlik va uning narxi — shu mashq uchun misol, «Bahor» menyusiga kirmaydi.
4-mashq: Portfolio qadami — menyuni topish
Keyingi darslarda portfolio'ga tema tugmasi va mobil menyu uchun kod qo'shiladi. Ular uchun avval kerakli elementlarni topib olish kerak. asosiy.js ga menyuniTop funksiyasini qo'shing:
nav[aria-label="Asosiy menyu"]ni toping (Atribut selektorlari).- Menyu bo'lmasa (
404.htmlda menyu yo'q) — funksiya hech narsa qilmay tugasin (erta qaytish). - Menyudagi havolalar sonini va joriy sahifa havolasining (
[aria-current="page"]) matnini konsolga chiqaring. Joriy havola topilmasa,?.bilanundefinedchiqsin, xato emas.
Yechim
asosiy.js ga (o'tgan darsdagi sahifaniTekshir dan keyin):
function menyuniTop() {
const menyu = document.querySelector(
'nav[aria-label="Asosiy menyu"]',
);
if (menyu === null) {
return;
}
const havolalar = menyu.querySelectorAll("a");
const joriy = menyu.querySelector('[aria-current="page"]');
console.log(`Menyuda ${havolalar.length} ta havola`);
console.log(`Joriy sahifa: ${joriy?.textContent}`);
}
menyuniTop();Natijani shu menyuga o'xshash parchada tekshiring:
<nav aria-label="Asosiy menyu">
<ul>
<li><a href="./">Bosh sahifa</a></li>
<li><a href="loyihalar/" aria-current="page">Loyihalar</a></li>
<li><a href="aloqa/">Aloqa</a></li>
</ul>
</nav>
<script>
function menyuniTop() {
const menyu = document.querySelector(
'nav[aria-label="Asosiy menyu"]',
);
if (menyu === null) {
return;
}
const havolalar = menyu.querySelectorAll("a");
const joriy = menyu.querySelector('[aria-current="page"]');
console.log(`Menyuda ${havolalar.length} ta havola`);
console.log(`Joriy sahifa: ${joriy?.textContent}`);
}
menyuniTop();
</script>Konsolda:
Menyuda 3 ta havola
Joriy sahifa: LoyihalarSizning portfolio'ngizda havolalar soni va nomlari boshqacha bo'lishi mumkin. 404.html da konsolda faqat "asosiy.js ulandi" chiqadi — menyu yo'q, funksiya jim tugadi. Selektordagi qo'shtirnoq: tashqisi bitta ('), ichkisi qo'sh (") — ikkalasi bir xil bo'lsa, satr erta yopilib qolardi.
Commit: JS: asosiy menyuni topish funksiyasini qo'sh.
13. Real ishda
- Har bir interaktiv sahifa tanlashdan boshlanadi: forma, tugma, modal oyna — avval
querySelector, keyin ish. - Avtomatik testlar (kursda alohida o'rganamiz) elementni ham shunday topadi: Playwright va Testing Library'da
page.locator(".narx")yoki "tugmani matni bo'yicha top" degan buyruqlar — aslida shu g'oya. - Selektor sifati — kod sifati.
div > div:nth-child(3) spankabi uzun selektor dizayn o'zgarishi bilan buziladi. Real loyihada JavaScript uchun aniq nomlar (id, ma'noliclass, keyinroqdata-*atributlari — dataset) ishlatiladi. - Brauzer kengaytmalari va skriptlar. Telegram Web yoki marketpleysdan narxlarni yig'adigan kichik vositalar ham sahifadan ma'lumotni aynan
querySelectorAllbilan oladi. Sayt dizayni o'zgarsa, ular birinchi bo'lib buziladi — mo'rt selektor muammosining eng yorqin namunasi. - Freymvorklarda (React va boshqalar — kursda alohida o'rganamiz) elementni qo'lda kamroq tanlaysiz, lekin forma maydoniga fokus berish yoki tashqi kutubxonani ulash uchun baribir kerak bo'ladi.
- Intervyuda: "
querySelectorAllvagetElementsByClassNamefarqi?" — javob: statikNodeListva jonliHTMLCollection.
Xulosa
getElementById("id")—#siz, bitta element yokinull.querySelector(selektor)— birinchi mos element yokinull;querySelectorAll— hammasi, statikNodeList(topilmasa — bo'sh ro'yxat).- Element ichida qidirish:
karta.querySelector(...); selektorni elementga bog'lash —:scope. closest— o'zidan yuqoriga qarab qidiradi;matches—true/falsebilan tekshiradi.HTMLCollectionvachildNodes— jonli; jonli ro'yxatni aylanib o'chirmang.- Noto'g'ri selektor —
SyntaxError, topilmagan element —null: ikkalasini farqlang.
Keyingi dars: Kontentni o'zgartirish va XSS xavfi — topgan elementingizga yangi matn yozamiz va innerHTML qanday qilib saytni hujumchiga ochib berishini ko'ramiz.
Manbalar
- MDN: "Document: querySelector() method", "Element: closest() method", "Element: matches() method" — developer.mozilla.org
- MDN: "NodeList", "HTMLCollection" — developer.mozilla.org
- MDN: ":scope" — developer.mozilla.org
- Chrome DevTools: "Console Utilities API reference" ($, $$) — developer.chrome.com
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!