IlmHamroh
JavaScript Full-stack/9-qism. JavaScript brauzerda va debugging1/29-dars23 daqiqa
Mundarija (29)

JavaScript brauzerda: window, document va skript qachon ishlaydi

Qisqacha: Brauzerda JavaScript tili o'sha, lekin unga brauzerning o'z asboblari qo'shiladi — ularni Web API deyishadi. Hammasi window degan katta obyektda turadi, sahifaning o'zi esa window.document da. Skript HTML o'qib bo'linmasdan ishlasa, sahifadagi teglarni topolmaydi va null oladi. Shuning uchun tashqi skript <head> ga defer bilan ulanadi.

Bu darsda

  • Node va brauzerdagi JavaScript farqini tushuntira olasiz: til bir xil, asboblar boshqa.
  • window, document, BOM va DOM nima ekanini va qaysi biri nimaga javob berishini bilasiz.
  • Web API nima ekanini va u qayerdan kelishini tushunasiz.
  • Skript nega null topishini tushuntirib, uni defer, type="module" yoki DOMContentLoaded bilan tuzata olasiz.
  • Portfolio'ngizga birinchi JavaScript faylini ulaysiz.

Oldin bilishingiz kerak: Yakuniy loyiha: oylik byudjet, Birinchi dastur: konsol va <script> tegi, Skriptlarni ulash: defer, async, module, Critical Rendering Path.

1. Nega bu kerak?

08-qism oxirida Aziz oylik byudjet dasturini yozdi. Dastur ishlaydi, lekin faqat terminalda. Aziz uni do'stiga ko'rsatmoqchi bo'ldi — do'sti terminal ochishni bilmaydi. Unga tugmali, ro'yxatli oddiy sahifa kerak.

Bu qismda JavaScript brauzerga ko'chadi. Til o'zgarmaydi: let, funksiya, massiv, for...of — hammasi o'sha. O'zgaradigani — atrof. Kod endi sahifa ichida yashaydi va sahifani o'zgartira oladi.

Lekin birinchi qadamda ko'p boshlovchi qoqiladigan tuzoq bor. Kod to'g'ri yozilgan, xato yo'qdek, lekin sahifada hech narsa o'zgarmaydi. Konsolda esa null turibdi. Bu dars aynan shu tuzoqning sababini ochadi.

1.1 Bu qismda misollar jonli

08-qismda kodni "Ishga tushir" tugmasi bilan ishlatardingiz va natija Node konsoli kabi matn bo'lib chiqardi. Endi kod sahifa ichida yashaydi, shuning uchun misollar boshqacha ko'rinadi. Bu qismdan boshlab deyarli har misol — jonli oyna: dars ichidagi kichik sahifa, u haqiqiy brauzerda ishlaydi.

Jonli oynaning uch qismi bor:

  1. Natija tabi — kod chizgan sahifa: sarlavha, matn, tugmalar. Tugmani bossangiz, haqiqatan bosiladi.
  2. Kod tabi — shu sahifaning HTML va JavaScript kodi. Kodning ostida Tahrirlab ko'rish tugmasi bor.
  3. Konsol paneli — Natija tabida, sahifaning ostida. console.log yozgan har bir narsa shu yerga tushadi. Kod hech narsa yozmasa, panel umuman chiqmaydi.

Konsol paneli — DevTools konsolining kichik nusxasi. Telefonda DevTools yo'q, shuning uchun telefonda o'qisangiz, kodning "ovozi" faqat shu panelda eshitiladi. Oddiy qatorlar odatiy rangda chiqadi, xatolar — qizil fonda, ogohlantirishlar (console.warn) — sariq fonda.

Birinchi oynani oching. U Kod tabi bilan ochiladi — avval kodni o'qing, keyin Natija tabini bosing:

html
<h1>«Bahor» choyxonasi</h1>
<p>Menyu tez orada shu yerda chiqadi.</p>
<script>
  console.log("Salom, brauzer!");
  console.log(2026 + 1);
</script>

Konsolda:

text
Salom, brauzer!
2027

Natija tabida sarlavha va matn chiqdi, ostidagi Konsol panelida esa ikki qator. E'tibor bering: "Salom, brauzer!" sahifada yo'q. console.log sahifaga emas, konsolga yozadi — mehmon uni ko'rmaydi, faqat dasturchi ko'radi.

Darsda har oynadan keyin Konsolda: deb, panelda nima chiqishi yozib qo'yiladi. Oynadagi panelni shu bilan solishtiring — bir xil bo'lishi kerak.

Endi o'zingiz o'zgartirib ko'ring:

  1. Kod tabini oching va Tahrirlab ko'rish ni bosing — kod yoziladigan maydonga aylanadi.
  2. 2026 + 1 o'rniga 35000 * 2 yozing.
  3. Kodning ostiga qarang: u yerda natija va Konsol paneli paydo bo'ldi. Yozishni to'xtatganingizdan keyin bir lahzada sahifa noldan qayta ishga tushadi va konsol yangi qatorlarni ko'rsatadi: 70000.
  4. Asl kodga qaytish uchun — Asl holiga qaytarish tugmasi.

Maslahat: Jonli oyna — saytdan ajratilgan alohida kichik sahifa. Unda nima qilsangiz ham, darsning o'ziga yoki saytga zarar yetmaydi. Kodni buzib qo'ysangiz ham qo'rqmang — "Asl holiga qaytarish" bor. Bemalol tajriba qiling.

Tekshirib ko'ring: Aziz kodga console.log("Osh tayyor"); qatorini qo'shdi, lekin sahifada "Osh tayyor" yozuvi chiqmadi. Kod buzildimi?

Javob

Yo'q, kod to'g'ri ishladi. console.log matnni sahifaga emas, Konsol paneliga yozadi — uni sarlavha ostida emas, oynaning eng pastida qidiring. Sahifadagi matnni JavaScript bilan o'zgartirishni shu darsning «document» bo'limida ko'ramiz.

2. Bitta til, ikki muhit

2.1 Dvigatel va muhit

Brauzer tuzilishi darsida ko'rgandingiz: Chrome ichida V8 degan JavaScript dvigateli ishlaydi. Node.js ham aynan shu V8 ustiga qurilgan.

Dvigatel faqat tilni biladi: o'zgaruvchi, funksiya, massiv, Math, JSON. U ekran, fayl yoki internet haqida hech narsa bilmaydi. Bularni muhit (host environment) beradi — dvigatel "o'rnatilgan" dastur. Node — bitta muhit, brauzer — ikkinchisi.

Hayotdan o'xshatish: avtomobil motori. Bitta motorni yuk mashinasiga ham, avtobusga ham qo'yish mumkin. Motor bir xil, lekin kuzov va asboblar har xil: yuk mashinasida yuk ortadigan joy, avtobusda o'rindiq va eshiklar. JavaScript'da motor — V8. Node "kuzovi" fayl va terminal bilan ishlaydi, brauzer "kuzovi" — sahifa, tugma va tarmoq bilan.

Diagrammada o'rtadagi dvigatel ikkala muhitda bir xil. Farq — atrofdagi asboblarda:

flowchart TD
  V["JavaScript dvigateli (V8): til"]
  N["Node muhiti"]
  B["Brauzer muhiti"]
  V --> N
  V --> B
  N --> N1["fayllar, terminal"]
  B --> B1["document: sahifa"]
  B --> B2["fetch, localStorage"]
  U["Ikkalasida: console, setTimeout"]
  N --> U
  B --> U

2.2 Nimasi umumiy, nimasi boshqa

Imkoniyat Node'da Brauzerda
let, funksiya, massiv, Math, JSON bor bor
console.log bor (terminalga) bor (DevTools konsoliga)
setTimeout bor bor
window, document, alert yo'q bor
Fayl o'qish, terminal argumentlari bor yo'q

Birinchi qator — tilning o'zi, u hamma joyda bir xil. 08-qismda o'rganganingizning deyarli hammasi shu qatorda. Demak, siz hech narsani qaytadan o'rganmaysiz — faqat yangi asboblar qo'shiladi.

Brauzer kodini Node'da ishga tushirsangiz nima bo'ladi?

js
console.log(document.title);

Terminalda:

text
ReferenceError: document is not defined

Tarjimasi: "document aniqlanmagan". Node'da sahifa yo'q, demak document ham yo'q. typeof darsida ko'rgan typeof window tekshiruvi aynan shu farq uchun kerak: Node'da u "undefined" beradi.

Tekshirib ko'ring: Aziz byudjet dasturidagi somYoz funksiyasini brauzerga ko'chirdi. U o'zgarishsiz ishlaydimi?

Javob

Ha. somYoz faqat tilning o'zidan foydalanadi: satr, sikl, Math.abs, %. Bular ikkala muhitda bir xil. Faqat Node'ga yoki faqat brauzerga tegishli asbob ishlatilgan kodgina ko'chganda buziladi.

3. window — brauzerning global obyekti

var darsida global obyekt bilan tanishgansiz: brauzerda u window deb ataladi va undagi narsalar istalgan joydan ko'rinadi. Endi uni yaqinroq ko'ramiz.

Har bir brauzer tabi uchun bitta window bor. U — brauzerning katta asboblar qutisi: konsol, taymer, oyna o'lchami, manzil satri va, eng muhimi, sahifaning o'zi. Shuning uchun console aslida window.console, document esa window.document:

html
<p>Bu sahifa — window ichidagi document.</p>
<script>
  console.log(typeof window);
  console.log(window === globalThis);
  console.log(window.document === document);
  console.log(window.console === console);

  var eskiUsul = "var";
  let yangiUsul = "let";
  console.log(window.eskiUsul, window.yangiUsul);
</script>

Konsolda:

text
object
true
true
true
var undefined

Qatorma-qator:

  • window — obyekt, va u globalThis ning o'zi. Node'da globalThis boshqa obyekt edi.
  • window.document va document — bitta narsa. window. qismini yozmasangiz ham bo'ladi.
  • Oxirgi qator — var darsidagi tanish tuzoq: tashqi var window ga yoziladi, let esa yozilmaydi.

Qachon window. ni yozish kerak? Odatda yozilmaydi: document, console, setTimeout. Faqat oynaning o'ziga tegishli narsada aniqlik uchun yoziladi. Masalan, window.innerWidth — oyna eni, pikselda. "Tahrirlab ko'rish" bilan console.log(window.innerWidth); qatorini qo'shing — jonli oynaning eni chiqadi. Telefonda bu son kichikroq bo'ladi. window. bilan yana bitta yozuvni shu darsning oxirida — hodisalarda ko'rasiz.

Diqqat: window ichida brauzerning yuzlab o'z nomlari bor: name, top, location, history, status. Ulardan ba'zilarini o'zgaruvchi nomi sifatida ishlatib bo'lmaydi. «Ko'p uchraydigan xatolar» bo'limida aniq misolini ko'ramiz.

4. BOM va DOM: window ichida nima bor

window ichidagi asboblarni ikki guruhga bo'lish qulay.

BOM (Browser Object Model, brauzer obyekt modeli) — brauzerning o'zi bilan ishlash uchun obyektlar. Sahifa bilan emas, uni o'rab turgan "ramka" bilan:

  • navigator — brauzer va qurilma haqida: tili, internet bormi.
  • location — manzil satri: hozirgi URL, boshqa sahifaga o'tish.
  • history — "Orqaga" va "Oldinga" tugmalari tarixi.
  • screen — ekran o'lchamlari.
  • alert, confirm, prompt — tayyor dialog oynalari.

DOM (Document Object Model, hujjat obyekt modeli) — sahifaning o'zi: document va uning ichidagi hamma element. Critical Rendering Path darsida DOM'ni brauzer HTML'dan quradigan daraxt sifatida ko'rgansiz. Endi JavaScript aynan shu daraxt bilan ishlaydi.

Diagrammada chap tomon — BOM, o'ng tomon — DOM. Ikkalasining ham "ildizi" window:

flowchart TD
  W["window"]
  W --> NAV["navigator"]
  W --> LOC["location"]
  W --> HIS["history"]
  W --> SCR["screen"]
  W --> D["document"]
  D --> H["html"]
  H --> HE["head"]
  H --> BO["body"]
  classDef bom fill:#fdeee6,stroke:#b4461a
  classDef dom fill:#e8f1ec,stroke:#1f6f4a
  class NAV,LOC,HIS,SCR bom
  class D,H,HE,BO dom

Hayotdan o'xshatish: choyxona binosi. BOM — bino haqidagi narsalar: manzil taxtachasi (location), kirish daftari (history), bino qaysi shaharda (navigator). DOM — zal ichidagi narsalar: stollar, menyu, devordagi yozuvlar. Mehmon ko'radigan va JavaScript o'zgartiradigan narsaning ko'pi — DOM'da.

Ikki nozik fakt:

  • "BOM" — dasturchilar orasidagi qulay atama, rasmiy standart nomi emas. Bu obyektlarning har biri HTML standartida alohida yozilgan. DOM esa o'z rasmiy standartiga ega.
  • DOM faqat JavaScript uchun emas: ekran o'quvchilar ham sahifani DOM'dan "o'qiydi". Shuning uchun DOM'ni to'g'ri o'zgartirish qulaylikka ham ta'sir qiladi.

4.1 BOM'ni o'zingiz ko'ring

Jonli oyna saytdan ajratilgan, shuning uchun BOM'ning ba'zi qismlari unda haqiqiy qiymat bermaydi: location.href o'rniga about:srcdoc chiqadi, alert esa jimgina e'tiborsiz qoldiriladi. BOM'ni haqiqiy saytda ko'rish uchun kompyuterda shu sahifada F12 ni bosing va DevTools'ning Console paneliga birma-bir yozib, Enter bosing. Telefonda o'qiyotgan bo'lsangiz — bu qadamni kompyuterga qoldiring, dars davomida unga tayanmaymiz.

Quyidagi kabi oddiy kod bloklari ostida "Ishga tushir" tugmasi yo'q: ular jonli oynaga sig'maydigan, faqat haqiqiy brauzerda ma'noli kod. Izohda har qator nima berishi yozilgan:

js
location.href;       // manzil satridagi to'liq manzil
location.hostname;   // faqat domen
navigator.language;  // brauzer tili, masalan "uz" yoki "ru-RU"
screen.width;        // ekran eni, pikselda
history.length;      // shu tabda nechta sahifa ochilgan

Javoblar har kimda har xil — brauzer, til va ekranga bog'liq. Shu farqning o'zi BOM nima ekanini ko'rsatadi: u sahifani emas, sizning brauzeringizni tasvirlaydi.

alert, confirm va prompt haqida bir gap. Birinchi darslarda alert bilan xabar chiqargansiz. Bu oynalar butun sahifani "muzlatadi": foydalanuvchi OK ni bosmaguncha hech narsa ishlamaydi. Ularni bezab ham bo'lmaydi. Shuning uchun real saytlarda ular deyarli ishlatilmaydi — o'rniga <dialog> elementi olinadi.

Tekshirib ko'ring: Qaysilari BOM, qaysilari DOM: navigator.language, document.title, location.reload(), document.body?

Javob

BOM: navigator.language (brauzer tili) va location.reload() (sahifani qayta yuklash — manzil satri bilan ishlash). DOM: document.title (sahifa sarlavhasi) va document.body (sahifaning body elementi). Qoida: document. bilan boshlansa — DOM.

5. Web API'lar: brauzer bergan asboblar

API (Application Programming Interface) — dasturlar bir-biri bilan gaplashadigan "eshik": bir dastur ikkinchisidan tayyor ish so'raydigan qoidalar to'plami. Web API — brauzer JavaScript'ga beradigan shunday tayyor imkoniyatlar.

Hayotdan o'xshatish: Telegram ilovasi telefon kamerasini o'zi yasamaydi. U telefon tizimidan "kamerani och" deb so'raydi. JavaScript ham shunday: sahifani o'zgartirish, internetdan ma'lumot olish, brauzer xotirasiga yozish — bularning hammasini brauzerdan so'raydi.

Kursda uchraydigan asosiy Web API'lar:

Web API Nima qiladi Qayerda o'rganamiz
DOM Sahifa elementlarini o'qish va o'zgartirish Shu qismda (DOM daraxti)
Hodisalar Bosish, yozish, aylantirishga javob addEventListener
fetch Serverdan ma'lumot olish fetch asoslari
localStorage Brauzerda ma'lumot saqlash Brauzer xotirasi
setTimeout Kodni kechiktirib bajarish Callback darsida ko'rgansiz

Muhim fakt: Web API'lar JavaScript tilining bir qismi emas. Til standartida (ECMAScript) document ham, fetch ham yo'q. Ular brauzer standartlarida yozilgan. Ba'zilari shunchalik foydali bo'lib chiqdiki, Node ham ularni o'ziga qo'shib olgan: console, setTimeout, fetch.

Yangi Web API'lar har yili chiqadi va hamma brauzerda bir vaqtda paydo bo'lmaydi. Shuning uchun yangi imkoniyatni ishlatishdan oldin u qaysi brauzerlarda borligini tekshirish odat — Veb standartlari darsidagi Baseline belgisi shunga yordam beradi.

Tekshirib ko'ring: Nega setTimeout ham Node'da, ham brauzerda bor, document esa faqat brauzerda?

Javob

Ikkalasi ham tilning emas, muhitning asbobi. Kechiktirib bajarish ikkala muhitda ham kerak — shuning uchun Node ham setTimeout ni qo'shgan. Sahifa esa faqat brauzerda bor, Node'da ko'rsatadigan sahifaning o'zi yo'q.

6. document — sahifaning JavaScript'dagi ko'rinishi

document — DOM daraxtining ildizi. Undan sahifaning istalgan qismiga yetib borish mumkin. Eng ko'p kerak bo'ladigan to'rttasi:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>«Bahor» — menyu</title>
</head>
<body>
  <h1>Menyu</h1>
  <script>
    console.log(document.title);
    console.log(document.documentElement);
    console.log(document.head);
    console.log(document.body);
  </script>
</body>
</html>

Konsolda:

text
«Bahor» — menyu
<html lang="uz">…</html>
<head>…</head>
<body>…</body>
  • document.title — <title> ichidagi matn, ya'ni brauzer tabidagi yozuv.
  • document.documentElement — <html> elementi.
  • document.head va document.body — <head> va <body>.

… belgisi "ichida boshqa elementlar bor, qisqartirildi" degani. Haqiqiy Chrome konsolida element yonida kichik uchburchak chiqadi — uni bosib ichini ochasiz. Jonli oynaning Konsol paneli esa uni qisqa matn qilib ko'rsatadi. Ma'nosi bir xil.

Konsolga chiqqan <head>…</head> — oddiy satr emas. Bu element: brauzer HTML'dagi tegni o'qib, xotirasida yasagan obyekt. Har bir teg uchun bittadan shunday obyekt bor. 08-qismdagi obyektlar kabi, elementning ham xususiyatlari va metodlari bor. Masalan, document.title — document obyektining xususiyati.

Diqqat: "Xususiyat" so'zi kursda ikki joyda uchraydi: CSS xususiyati (color: red dagi color) va JavaScript obyektining xususiyati (document.title dagi title). Bu qismda deyarli har doim ikkinchisi — obyekt xususiyati nazarda tutiladi.

console API darsida console.dir ni eslatib, "foydasini brauzer qismida ko'rasiz" degan edik. U elementni HTML ko'rinishida emas, aynan obyekt sifatida ochadi — buni keyingi darsda, DOM daraxtini o'rganganda sinaymiz.

Endi birinchi marta sahifani o'zgartiramiz. Ikki yangi asbob kerak, ikkalasini keyingi darslarda to'liq o'rganasiz:

  • document.querySelector("h1") — sahifadan CSS selektor bo'yicha birinchi mos elementni topib beradi. Selektor — CSS'dagi h1, .narx kabi "qaysi teglar" degan yozuv. Topmasa — null qaytaradi (Elementlarni tanlash).
  • element.textContent — elementning xususiyati: ichidagi matn. Unga yangi qiymat bersangiz, matn almashadi (Kontentni o'zgartirish).
html
<h1>Menyu</h1>
<p>Bugun: osh, manti, lag'mon.</p>
<script>
  const sarlavha = document.querySelector("h1");
  console.log(sarlavha);

  sarlavha.textContent = "Bugungi menyu";
  console.log(sarlavha);
</script>

Konsolda:

text
<h1>Menyu</h1>
<h1>Bugungi menyu</h1>

Natija tabiga qarang: sarlavhada "Menyu" emas, "Bugungi menyu" turibdi. HTML'da esa "Menyu" yozilgan! JavaScript sahifani brauzer xotirasidagi DOM'da o'zgartirdi.

Bu o'zgarish faylga yozilmaydi. DevTools darsida Elements panelida qilgan o'zgarishlaringiz kabi, u faqat shu ochiq sahifada yashaydi. Farqi — endi o'zgarishni siz qo'lda emas, kod qiladi va kod har safar sahifa ochilganda qayta ishlaydi.

Tekshirib ko'ring: Yuqoridagi misolda sahifani yangilasangiz (F5), sarlavhada nima turadi — "Menyu" yoki "Bugungi menyu"?

Javob

"Bugungi menyu". Yangilanganda brauzer HTML'ni qaytadan o'qiydi va bir lahza "Menyu" ni quradi, lekin skript yana ishlab, uni darhol almashtiradi. HTML fayl esa o'zgarmagan — skriptni o'chirsangiz, "Menyu" qaytadi.

7. Skript qachon ishlaydi va nega null chiqadi

7.1 Muammo: skript sahifadan oldin keldi

Birinchi dastur darsidan eslaysiz: brauzer HTML'ni yuqoridan pastga o'qiydi. Oddiy <script> ga yetsa — to'xtaydi, skriptni bajaradi, keyin davom etadi. Demak, <head> dagi skript ishlayotganda <body> hali o'qilmagan. Uning elementlari DOM'da yo'q.

O'tgan misoldagi kodni so'zma-so'z <head> ga ko'chiramiz:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Menyu</title>
  <script>
    console.log(document.readyState);
    const sarlavha = document.querySelector("h1");
    console.log(sarlavha);
    sarlavha.textContent = "Bugungi menyu";
  </script>
</head>
<body>
  <h1>Menyu</h1>
</body>
</html>

Konsolda:

text
loading
null
Uncaught TypeError: Cannot set properties of null (setting 'textContent')

Uchala qatorni o'qiymiz:

  • loading — document.readyState (hujjat holati): "sahifa hali yuklanmoqda".
  • null — querySelector h1 ni topmadi. U hali yo'q-da.
  • Qizil xato. Tarjimasi: "null ning xususiyatini o'rnatib bo'lmaydi ('textContent' ni o'rnatayotganda)". Ya'ni: siz null ga textContent yozmoqchi bo'ldingiz.

E'tibor bering: xato sarlavha.textContent = ... qatorida chiqdi, lekin aybdor bitta yuqoridagi qator — querySelector hech narsa topmagan. Qoida: Cannot ... properties of null ni ko'rsangiz, o'sha o'zgaruvchiga qiymat bergan qatorga qayting va so'rang: "element topildimi?" Matnni o'qimoqchi bo'lsangiz, xato boshqacha boshlanadi — Cannot read properties of null (reading 'textContent') — sababi esa o'sha.

Hayotdan o'xshatish: ofitsiant Otabek ertalab choyxona eshigi ochilmasdan zalga chiqib, "3-stol, buyurtma bering!" dedi. Javob yo'q — zal bo'm-bo'sh, mehmonlar hali kirmagan. Otabekda xato yo'q, u faqat erta chiqdi.

document.readyState uch qiymatdan birini oladi:

Qiymat Ma'nosi
"loading" HTML hali o'qilyapti
"interactive" HTML o'qib bo'lindi, DOM tayyor; rasmlar hali yuklanishi mumkin
"complete" Hamma narsa yuklandi: rasmlar, shriftlar, uslublar

7.2 Uch yechim

1. Skriptni </body> oldiga qo'yish. Skriptga yetguncha butun body o'qilgan bo'ladi. Bu eski, lekin ishlaydigan usul — yuqoridagi barcha misollar shunday yozilgan. Kamchiligi: tashqi fayl bo'lsa, brauzer uni yuklashni faqat HTML oxiriga yetganda boshlaydi.

2. Tashqi faylga defer. HTML qismida o'rgangan usul: fayl fonda yuklanadi, HTML to'liq o'qilgach bajariladi.

html
<head>
  <meta charset="utf-8">
  <title>Menyu</title>
  <script src="assets/js/asosiy.js" defer></script>
</head>

Jonli oyna tashqi faylni ocholmaydi, shuning uchun bu misol oddiy kod bloki. O'zingiz sinamoqchi bo'lsangiz — «Portfolio qadami» mashqida aynan shunday faylni ulaysiz.

3. type="module". Modul skript defer kabi ishlaydi — va bu ichki skriptga ham tegishli:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Menyu</title>
  <script type="module">
    const sarlavha = document.querySelector("h1");
    console.log(sarlavha);
    sarlavha.textContent = "Bugungi menyu";
    console.log(sarlavha);
  </script>
</head>
<body>
  <h1>Menyu</h1>
</body>
</html>

Konsolda:

text
<h1>Menyu</h1>
<h1>Bugungi menyu</h1>

Kod <head> da, lekin u HTML o'qib bo'lingach ishladi: h1 endi topildi. Modullarning boshqa xususiyatlari ham bor (o'z scope'i, import) — ularni modullar qismida o'rganamiz, hozir bilish shart emas.

Kursdagi kelishuv: sahifa kodi alohida faylda, <head> ichida, defer bilan. Jonli oynalarda esa qisqalik uchun skript ko'pincha body oxirida turadi — natija bir xil.

7.3 Ikki signal: DOMContentLoaded va load

Ba'zan skriptni defer siz, <head> da qoldirishga to'g'ri keladi: eski loyiha, begona kod. Shunda brauzerning o'zidan "sahifa tayyor bo'lganda ayt" deb so'rash mumkin.

Hodisa (event) — brauzerning "shu narsa yuz berdi" degan xabari: tugma bosildi, sahifa yuklandi, oyna o'lchami o'zgardi. Hodisani addEventListener bilan tinglaymiz. Hodisalarni addEventListener asoslari darsida to'liq o'rganamiz. Hozircha bitta qolip yetadi:

js
document.addEventListener("DOMContentLoaded", () => {
  // DOM tayyor bo'lganda shu yer bajariladi
});

O'qilishi: "document da DOMContentLoaded hodisasi bo'lganda, shu funksiyani chaqir". Funksiyani o'zimiz chaqirmaymiz — uni brauzerga beramiz, u keyin chaqiradi. Bu callback — 08-qismdan tanish g'oya.

Ikki muhim hodisa bor:

  • DOMContentLoaded — HTML o'qib bo'lindi, DOM tayyor. Rasmlarni kutmaydi.
  • load — hamma narsa yuklandi: rasmlar, shriftlar, uslublar. U window da tinglanadi.

Qaysi biri qachon kelishini konsolda ko'ramiz. Raqamlar — kutilgan tartib:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Menyu</title>
  <script>
    console.log("1. head skripti:", document.readyState);
    document.addEventListener("DOMContentLoaded", () => {
      console.log("3. DOMContentLoaded:", document.readyState);
    });
    window.addEventListener("load", () => {
      console.log("4. load:", document.readyState);
    });
  </script>
</head>
<body>
  <h1>Menyu</h1>
  <script>
    console.log("2. body oxiri:", document.readyState);
  </script>
</body>
</html>

Konsolda:

text
1. head skripti: loading
2. body oxiri: loading
3. DOMContentLoaded: interactive
4. load: complete

Head skripti birinchi ishladi, lekin ikki funksiyani "keyinga" qoldirdi. Ular o'z hodisasi kelganda chaqirildi. Ikkinchi qatorga ham qarang: body oxiridagi skript ishlayotganda holat hali loading — brauzer </html> gacha yetmagan, lekin h1 allaqachon DOM'da.

Butun yo'lni vaqt bo'yicha diagrammada ko'ring — yuqoridan pastga:

sequenceDiagram
  participant H as HTML o'qish
  participant S as Skriptlar
  participant B as Brauzer signallari
  H->>S: oddiy skript — o'qish to'xtaydi
  S-->>H: bajarildi, davom et
  Note over H: HTML tugadi (interactive)
  H->>S: defer va module skriptlar
  S-->>B: tugadi
  B->>B: DOMContentLoaded
  Note over B: rasmlar, shriftlar yuklanadi
  B->>B: load (complete)

Qaysi birini tanlash kerak?

  • defer bo'lsa — hech qaysi. defer skript DOMContentLoaded dan oldin, DOM tayyor bo'lgach ishlaydi. Qo'shimcha "o'ram" kerak emas.
  • DOMContentLoaded — defer siz, <head> dagi skript uchun. Eski kodda juda ko'p uchraydi.
  • load — rasmlar o'lchami kabi to'liq yuklangan narsa kerak bo'lsagina. Bu kamdan-kam holat: rasmlar ko'p bo'lsa, load sezilarli kechikadi.

Sahifaning boshqa signallari (tab yashirildi, sahifa yopilyapti) — Sahifa hayot sikli darsida.

Tekshirib ko'ring: Sahifada 20 ta katta rasm bor. Menyu tugmasi rasmlar yuklanishini kutmasdan ishlashi kerak. Kodni DOMContentLoaded ga yozasizmi yoki load ga?

Javob

DOMContentLoaded ga (yoki undan ham yaxshisi — defer li faylga, o'ramsiz). Tugma DOM'da bo'lishi kifoya. load esa 20 ta rasmning hammasini kutadi — sekin internetda foydalanuvchi bir necha soniya ishlamaydigan tugmani bosib turadi.

8. DevTools'da skriptlarni kuzatish

Skript umuman yuklandimi — buni kompyuterda, DevTools'da ikki joyda tekshirasiz:

  • Sources paneli, chapdagi Page daraxti — sahifa yuklagan barcha fayllar. assets/js/asosiy.js shu yerda ko'rinsa, fayl yuklangan. Uni bosib, kodini ochish mumkin (DevTools bilan debug darsida breakpoint shu yerda qo'yilgan edi).
  • Network paneli, JS filtri — har bir skript so'rovi va uning holati. 200 — yuklandi, 404 — fayl topilmadi.

Fayl yo'li xato bo'lsa, Console'da qizil xabar chiqadi:

text
Failed to load resource: the server responded with a status of 404 (Not Found)

Tarjimasi: "Resursni yuklab bo'lmadi: server 404 (topilmadi) holati bilan javob berdi". Xabarning o'ng tomonida qaysi fayl topilmagani yozilgan. Bunday holatda skriptning birorta qatori ham ishlamaydi — konsolda sizning console.log laringiz ham chiqmaydi. "Hech narsa chiqmadi" — avval Network'ga qarang.

9. Ko'p uchraydigan xatolar

9.1 Ichki skriptga defer yozish

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Menyu</title>
  <script defer>
    console.log(document.querySelector("h1"));
  </script>
</head>
<body>
  <h1>Menyu</h1>
</body>
</html>

Konsolda:

text
null

defer faqat src li tashqi skriptda ishlaydi. Ichki skriptda brauzer uni jimgina e'tiborsiz qoldiradi — xato ham, ogohlantirish ham yo'q. Tuzatish: kodni alohida faylga chiqarib src + defer bilan ulang yoki type="module" yozing.

9.2 Brauzer nomini o'zgaruvchiga berish

html
<p>Manzil</p>
<script>
  const location = "Toshkent, Chilonzor";
  console.log(location);
</script>

Konsolda:

text
Uncaught SyntaxError: Identifier 'location' has already been declared

Tarjimasi: "location nomi allaqachon e'lon qilingan". Siz uni hech qayerda e'lon qilmadingiz — lekin brauzer qilgan: bu window.location. top, document, window nomlari bilan ham shunday bo'ladi. SyntaxError bo'lgani uchun skriptning birorta qatori ham ishlamadi.

Bu yerda o'zbekcha nomlar yordam beradi: manzil nomi hech qachon to'qnashmaydi. Inglizcha nomlarga o'tganda (userLocation, cityName) — umumiy so'zni yolg'iz ishlatmang.

9.3 DOMContentLoaded ni kech tinglash

Hodisa bir marta bo'ladi. Tinglovchi undan keyin qo'shilsa, funksiya hech qachon chaqirilmaydi. Buni setTimeout bilan "kechikkan skript"ni taqlid qilib ko'ramiz:

html
<h1>Menyu</h1>
<script>
  setTimeout(() => {
    console.log("Holat:", document.readyState);
    document.addEventListener("DOMContentLoaded", () => {
      console.log("Bu qator hech qachon chiqmaydi");
    });
  }, 100);
</script>

Konsolda:

text
Holat: complete

Real hayotda bu async skript yoki kech yuklangan kutubxonada bo'ladi. Ishonchli qolip — avval holatni tekshirish:

js
function menyuniTayyorla() {
  console.log("Menyu tayyor");
}

if (document.readyState === "loading") {
  document.addEventListener("DOMContentLoaded", menyuniTayyorla);
} else {
  menyuniTayyorla();
}

E'tibor bering: menyuniTayyorla qavssiz berildi. Qavs bilan yozsangiz, funksiya darhol chaqirilardi va brauzerga natijasi (undefined) berilardi.

9.4 Node'da brauzer kodini ishlatish

node menyu.js → ReferenceError: document is not defined. Sababi «Bitta til, ikki muhit» bo'limida: Node'da sahifa yo'q. document ishlatgan fayl — brauzer uchun: HTML'ga ulang va Live Server bilan oching.

10. Mashqlar

1-mashq (oson): Qayerda ishlaydi?

Har qator uchun ayting: faqat brauzerda, faqat Node'da yoki ikkalasida.

  1. console.log(Math.max(3, 7));
  2. document.title = "Menyu";
  3. navigator.language
  4. [35000, 28000].includes(28000)
  5. alert("Xush kelibsiz!");
  6. setTimeout(() => console.log("tayyor"), 1000);
Yechim
# Qayerda Nega
1 Ikkalasida Math va console
2 Brauzerda document — DOM
3 Brauzerda navigator — BOM
4 Ikkalasida Massiv metodi — tilning o'zi
5 Brauzerda alert — BOM dialogi
6 Ikkalasida Ikkala muhit ham setTimeout beradi

2-mashq (o'rta): Skriptni tuzating

Quyidagi sahifada narx yangilanmaydi, konsolda qizil xato. "Tahrirlab ko'rish" bilan uni ikki xil usulda tuzating: avval skriptni ko'chirib, keyin uni joyida qoldirib.

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Narx</title>
  <script>
    const narx = document.querySelector(".narx");
    narx.textContent = "38 000 so'm";
  </script>
</head>
<body>
  <p>Osh — <span class="narx">35 000 so'm</span></p>
</body>
</html>

Ishora: ko'chirish — body ichiga, elementdan keyin. Joyida qoldirish — type atributi bilan («Uch yechim» bo'limidagi oxirgi usul).

Yechim

1-usul — skript body oxirida:

html
<p>Osh — <span class="narx">35 000 so'm</span></p>
<script>
  const narx = document.querySelector(".narx");
  narx.textContent = "38 000 so'm";
  console.log(narx);
</script>

Konsolda:

text
<span class="narx">38 000 so'm</span>

2-usul — skript <head> da, lekin modul:

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Narx</title>
  <script type="module">
    const narx = document.querySelector(".narx");
    narx.textContent = "38 000 so'm";
    console.log(narx);
  </script>
</head>
<body>
  <p>Osh — <span class="narx">35 000 so'm</span></p>
</body>
</html>

Konsolda:

text
<span class="narx">38 000 so'm</span>

Uchinchi to'g'ri yo'l ham bor — kodni DOMContentLoaded ichiga o'rash. Real loyihada esa to'rtinchisi eng yaxshisi: kod alohida faylda, defer bilan. 38 000 — shu mashq uchun o'ylab topilgan narx, «Bahor» menyusi o'zgarmaydi.

3-mashq (qiyin): Tartibni toping

Kodni ishga tushirmasdan, konsolda qaysi tartibda chiqishini yozing. Keyin Natija tabida tekshiring.

html
<!DOCTYPE html>
<html lang="uz">
<head>
  <meta charset="utf-8">
  <title>Tartib</title>
  <script type="module">
    console.log("B");
  </script>
  <script>
    console.log("A");
    document.addEventListener("DOMContentLoaded", () => {
      console.log("D");
    });
  </script>
</head>
<body>
  <h1>Menyu</h1>
  <script>
    console.log("C");
  </script>
</body>
</html>
Yechim

Konsolda:

text
A
C
B
D
  • A — oddiy skript, brauzer unga yetishi bilan bajariladi.
  • B modul bo'lgani uchun A dan oldin yozilgan bo'lsa ham kechiktiriladi.
  • C — body dagi oddiy skript, u ham o'qilishi bilan bajariladi. HTML hali tugamagan, shuning uchun modul hali kutyapti.
  • HTML tugadi → B (modul) bajariladi → shundan keyingina D (DOMContentLoaded).

Asosiy saboq: yozilgan joy emas, skript turi bajarilish vaqtini belgilaydi.

4-mashq: Portfolio qadami — birinchi JavaScript fayli

Portfolio'ngiz hozircha faqat HTML va CSS. Bugun unga JavaScript ulanadi — keyingi darslarda shu faylga tema tugmasi va forma tekshiruvi qo'shiladi.

  1. kurs/portfolio/sayt/assets/ ichida js papkasini va unda asosiy.js faylini yarating.
  2. Faylga bitta qator yozing: konsolga "asosiy.js ulandi" va sahifa sarlavhasini (document.title) chiqarsin. Template literal ishlating (Template literals).
  3. Faylni oltita sahifaning hammasiga <head> ichida, CSS havolasidan keyin defer bilan ulang. Yo'l — CSS'dagidek nisbiy: bosh sahifada assets/js/asosiy.js, ichki sahifalarda ../ bilan, 404.html da esa / bilan boshlanadi (CSS ulash darsidagi qoida).
  4. Live Server bilan oching, Console'da xabarni, Network'da 200 holatini tekshiring. Har sahifada sarlavha boshqacha chiqishi kerak.
  5. npm run check, keyin commit: JS: asosiy.js ni barcha sahifalarga ula va git push.
Yechim

sayt/assets/js/asosiy.js:

js
// asosiy.js — portfolio'ning umumiy skripti (09-qism)
console.log(`asosiy.js ulandi: ${document.title}`);

Ulash qatori — sahifaga qarab:

Sahifa src qiymati
index.html assets/js/asosiy.js
haqimda/, aloqa/, loyihalar/ ../assets/js/asosiy.js
loyihalar/bahor/ ../../assets/js/asosiy.js
404.html /assets/js/asosiy.js

Bosh sahifaning <head> qismi (boshqa qatorlar o'zgarmaydi):

html
<link rel="stylesheet" href="assets/css/asosiy.css">
<script src="assets/js/asosiy.js" defer></script>

Bosh sahifada Console'da shunday chiqadi:

text
asosiy.js ulandi: Aziz Karimov — boshlovchi frontend dasturchi

Sarlavha — o'zingizning <title> ingiz. Agar chiqmasa: Network'da 404 bormi (yo'l xato), yoki defer dan oldin src yozilganmi. console.log qatori — vaqtinchalik tekshiruv; keyingi darslarda uning o'rniga haqiqiy kod keladi.

11. Real ishda

  • Har bir sayt shu savoldan boshlanadi: skript qayerda va qanday ulanadi. Lighthouse "Eliminate render-blocking resources" deb ogohlantirsa, birinchi tekshiriladigan narsa — defer siz skriptlar (DevTools II: Lighthouse).
  • Zamonaviy vositalar (masalan Vite — kursda alohida o'rganamiz) saytni yig'ganda skriptni o'zi type="module" bilan ulaydi. Bugungi bilim sizga ular nega shunday qilishini tushunishga yordam beradi.
  • Begona kod — analitika, chat vidjeti — odatda async bilan ulanadi va ko'pincha "kech tinglash" tuzog'iga tushadi. readyState qolipi shu uchun kerak.
  • Intervyuda tez-tez so'raladi: "window va document farqi?", "defer va async farqi?", "DOMContentLoaded va load farqi?" Bugun uchalasiga javob berishni o'rgandingiz.

Xulosa

  • JavaScript tili Node'da ham, brauzerda ham bir xil; farq — muhit beradigan asboblarda (Web API'lar).
  • window — brauzerning global obyekti; document, console, setTimeout uning ichida.
  • BOM — brauzer bilan ishlash (navigator, location, history), DOM — sahifa bilan (document).
  • Skript HTML'dan oldin ishlasa, querySelector null beradi va Cannot ... properties of null xatosi chiqadi.
  • Yechim: tashqi fayl + defer (kurs kelishuvi), type="module" yoki DOMContentLoaded.
  • DOMContentLoaded — DOM tayyor; load — hamma narsa yuklandi.

Keyingi dars: DOM daraxti va tugun turlari — document ichiga kirib, sahifa qanday "tugunlardan" qurilganini ko'ramiz.

Manbalar

  • MDN: "Window", "Document", "Document: DOMContentLoaded event", "Document: readyState property" — developer.mozilla.org
  • MDN: "The Script element" — developer.mozilla.org
  • HTML Standard: "Scripting" — html.spec.whatwg.org
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript brauzerda: window, document va skript qachon ishlaydi — IlmHamroh