IlmHamroh
JavaScript Full-stack/9-qism. JavaScript brauzerda va debugging28/29-dars24 daqiqa
Mundarija (34)

Stack trace va JavaScript xato turlari: xato xabarini brauzerda va Node'da o'qish

Qisqacha: JavaScript xatosi uch qismdan iborat: turi (masalan TypeError), matni va stack trace — xato chiqqan joydan boshlab "kim kimni chaqirgan" ro'yxati. Stack trace tepadan pastga o'qiladi: eng yuqoridagi o'z faylingiz qatori — xato yiqilgan joy. Turi esa qayerdan qidirishni aytadi: SyntaxError — yozuvda, ReferenceError — nomda, TypeError — qiymat turida, RangeError — chegarada.

Bu darsda

  • Chrome DevTools va Node'dagi stack trace'ni qatorma-qator o'qiysiz va farqlarini bilasiz.
  • Uncaught, <anonymous>, HTMLButtonElement.<anonymous> kabi yozuvlar nimani anglatishini tushunasiz.
  • Oltita xato turini va ularning eng ko'p uchraydigan xabarlarini tanib, tarjima qilasiz.
  • Sabablar zanjirini (cause) o'qiysiz va asinxron xato hamda source map nima ekanini bilasiz.
  • console.trace va console.assert bilan kod yo'lini o'zingiz ko'rsatasiz.

Oldin bilishingiz kerak: Debugging metodologiyasi, Xato xabarini o'qish san'ati, DevTools bilan debug qilish, addEventListener asoslari.

1. Nega bu kerak?

O'tgan darsda eng ayyor xatoni — jim xatoni ovladik: konsol bo'sh, natija noto'g'ri. Qizil xato bilan ish ancha oson, chunki u nima bo'lganini va qayerda bo'lganini o'zi aytadi. Faqat uning tilini bilish kerak.

Xato xabarini o'qish darsida Node'dagi xabarning anatomiyasini ko'rgansiz: tur, matn, fayl:qator:ustun, stack trace. O'shanda kodni hali bilmas edingiz. Endi bilasiz — va xatolar ham murakkablashdi: tugma bosilganda, sikl ichida, taymerdan keyin chiqadi.

Bugungi vaziyat: dizayner Nodira savat sahifasida <output id="jami"> ni id="jami-summa" ga o'zgartirdi — CSS'da shunday nom kerak bo'lgan. Endi tugma bosilganda konsolda qizil xato chiqadi. Keling, uni o'qiymiz.

2. Xato xabarining uch qismi

Tugmani bosing va konsolga qarang:

html
<button type="button" data-narx="35000">Osh</button>
<button type="button" data-narx="28000">Lag'mon</button>
<p>Jami: <output id="jami-summa">0</output> so'm</p>
<script>
  let jami = 0;

  function jaminiYangila() {
    const jamiQator = document.querySelector("#jami");
    jamiQator.textContent = jami;
  }

  function savatgaQosh(narx) {
    jami += narx;
    jaminiYangila();
  }

  const tugmalar = document.querySelectorAll("[data-narx]");
  for (const tugma of tugmalar) {
    tugma.addEventListener("click", () => {
      savatgaQosh(Number(tugma.dataset.narx));
    });
  }
</script>

Osh ni bosganingizda — sahifa ochilganda emas — konsolda shunday qator chiqadi:

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

Uni bo'laklarga ajratamiz:

Qism Misolda Ma'nosi
Belgi Uncaught Xatoni hech kim ushlamadi
Turi (name) TypeError Xatoning toifasi
Matni (message) Cannot set properties of null… Aniq nima bo'ldi
Izi (stack) Jonli oynada ko'rinmaydi Xato qayerga qanday yo'l bilan yetdi

Tarjimasi: "null ning xususiyatini o'rnatib bo'lmaydi (textContent ni o'rnatayotganda)".

Uncaught — "ushlanmagan". JavaScript'da xatoni maxsus try/catch bloki bilan "ushlab", dasturni yiqitmasdan boshqarish mumkin. Uni try / catch / finally darsida o'rganamiz, hozir bilish shart emas. Bugungi hamma xatolar — ushlanmagan.

Yana bir fakt: xato — oddiy matn emas, obyekt. Uning name, message va stack xususiyatlari bor, jadvaldagi uch qism aynan shular. O'zingiz xato obyekti yaratishni throw va Error obyekti darsida ko'rasiz.

Endi Lag'mon ni bosing — yana xuddi shu xato. Brauzerda xato faqat shu hodisa ishini to'xtatadi: sahifa ishlashda davom etadi, keyingi bosish yana tinglovchini chaqiradi. Ichkarida esa jami ga narx qo'shilib ulgurgan — xato undan keyingi qatorda chiqdi. Ekran 0 ko'rsatadi, xotirada 63000. Xatodan keyin holat yarim o'zgargan bo'lishi mumkin — buni yodda tuting.

Tekshirib ko'ring: Xabarda null so'zi bor. U qaysi qiymat haqida gapiryapti va nega u null?

Javob

jamiQator haqida. document.querySelector("#jami") sahifadan #jami ni topa olmadi — endi element id="jami-summa" — va null qaytardi (Elementlarni tanlash). Keyingi qator null ga textContent yozmoqchi bo'ldi.

3. Brauzerda stack trace'ni o'qish

3.1 DevTools'dagi to'liq iz

Jonli oyna konsoli xabarning faqat birinchi qatorini ko'rsatadi. To'liq izni ko'rish uchun xuddi shu kodni faylga ko'chiramiz. assets/js/asosiy.js — qator raqamlari muhim, shuning uchun aynan shunday:

js
let jami = 0;

function jaminiYangila() {
  const jamiQator = document.querySelector("#jami");
  jamiQator.textContent = jami;
}

function savatgaQosh(narx) {
  jami += narx;
  jaminiYangila();
}

const tugmalar = document.querySelectorAll("[data-narx]");
for (const tugma of tugmalar) {
  tugma.addEventListener("click", () => {
    savatgaQosh(Number(tugma.dataset.narx));
  });
}

HTML'dan <script> ni olib, <head> ga <script src="assets/js/asosiy.js" defer></script> qo'ying, Live Server bilan oching va tugmani bosing. Chrome 154 konsolida:

text
Uncaught TypeError: Cannot set properties of null (setting 'textContent')
    at jaminiYangila (http://127.0.0.1:5500/assets/js/asosiy.js:5:25)
    at savatgaQosh (http://127.0.0.1:5500/assets/js/asosiy.js:10:3)
    at HTMLButtonElement.<anonymous> (http://127.0.0.1:5500/assets/js/asosiy.js:16:5)

DevTools manzilni havola qilib ko'rsatadi va ko'pincha qisqartiradi — faqat fayl nomi va raqamlar qoladi (asosiy.js:5:25). Havolani bossangiz, Sources paneli aynan o'sha qatorda ochiladi.

3.2 Qatorma-qator

Har at qatori — bitta chaqiruv: at funksiya_nomi (fayl:qator:ustun). Tepadan pastga:

  1. at jaminiYangila (…asosiy.js:5:25) — xato aynan shu yerda chiqdi: 5-qator, 25-ustun. Ustun — qator boshidan nechanchi belgi; bu yerda u = ni ko'rsatyapti, ya'ni xato qiymat yozilayotgan paytda chiqdi.
  2. at savatgaQosh (…:10:3) — jaminiYangila ni 10-qatordan savatgaQosh chaqirgan.
  3. at HTMLButtonElement.<anonymous> (…:16:5) — savatgaQosh ni 16-qatordagi nomsiz funksiya chaqirgan. <anonymous> — "nomsiz", ya'ni bizning strelkali funksiyamiz. HTMLButtonElement. — u tugma elementining tinglovchisi sifatida ishlagan.

Zanjir shu yerda tugaydi: tinglovchini kodimiz emas, brauzer chaqirgan — foydalanuvchi bosgani uchun. Diagrammada vaqt chapdan o'ngga ketadi, stack trace esa uni teskari — portlash joyidan boshlab — aytadi:

flowchart LR
  K["Bosish"] --> A["tinglovchi: 16-qator"]
  A --> B["savatgaQosh: 10-qator"]
  B --> C["jaminiYangila: 5-qator"]
  C --> X["TypeError"]

DevTools darsidagi Call Stack paneli ham xuddi shu ro'yxat — faqat u pauza paytida, stack trace esa xato paytida olingan "surat".

3.3 Yiqilgan joy va aybdor joy

Stack trace xato qayerda yiqilganini aytadi. Lekin nega — buni siz topasiz. 5-qatorda hech qanday xato yo'q: jamiQator.textContent = jami — to'g'ri yozuv. Aybdor qiymat bir qator yuqorida tug'ilgan (querySelector → null), uning sababi esa HTML'da: id o'zgargan.

Qoida: stack trace — tergovning boshlanishi. U sizni yiqilgan joyga olib boradi. U yerdan "bu qiymat qayerdan keldi?" deb orqaga yurasiz — debugging metodologiyasi darsidagi usul bilan.

Tekshirib ko'ring: Nodira id ni qaytarmaslikni so'radi. Kodda qaysi qatorni o'zgartirasiz?

Javob

4-qatorni: document.querySelector("#jami-summa"). Xato 5-qatorda chiqqan bo'lsa ham, uni tuzatish kerak emas — u faqat "topilmagan" qiymatning qurboni.

3.4 Nomsiz funksiyalar va brauzerning o'z kodi

Boshqa sahifa. Bu yerda har taomga holat yozuvi qo'shiladi:

js
const taomlar = document.querySelectorAll(".taom");

function belgila(taom) {
  const holat = taom.dataset.holat.toUpperCase();
  taom.textContent += ` (${holat})`;
}

taomlar.forEach((taom) => {
  belgila(taom);
});

HTML'da birinchi li da data-holat="yangi" bor, ikkinchisida yo'q. Chrome konsolida:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'toUpperCase')
    at belgila (http://127.0.0.1:5500/assets/js/asosiy.js:4:36)
    at http://127.0.0.1:5500/assets/js/asosiy.js:9:3
    at NodeList.forEach (<anonymous>)
    at http://127.0.0.1:5500/assets/js/asosiy.js:8:9

Ikki yangi ko'rinish:

  • at http://…asosiy.js:9:3 — funksiya nomi umuman yo'q. Bu — forEach ga berilgan strelkali funksiya, unga nom bermaganmiz. Oxirgi qator (8:9) — faylning o'zi, hech qanday funksiya ichida emas.
  • at NodeList.forEach (<anonymous>) — brauzerning o'z kodi: forEach metodi. Uning fayli yo'q, shuning uchun <anonymous>. Bunday qatorlarni o'tkazib yuborasiz.

Qoida — Xato xabarini o'qish darsidagi bilan bir xil: o'z faylingiz turgan eng yuqori qatorni toping. Bu yerda u birinchi qatorning o'zi: belgila, 4-qator.

Nomsiz funksiyalar ko'p bo'lsa, iz o'qilishi qiyinlashadi: at http://…:9:3 dan ko'ra at belgila ancha tushunarli. Shuning uchun murakkab kodda funksiyalarga nom berish foydali (funksiya — obyekt sifatida).

Tekshirib ko'ring: Sahifada "Osh (YANGI)" yozuvi paydo bo'ladimi?

Javob

Ekranda — ha. Birinchi li da data-holat bor: belgila uni muvaffaqiyatli ishladi. Xato faqat ikkinchi li da chiqdi va forEach shu yerda to'xtadi. Agar uchinchi taom bo'lganida, unga navbat kelmasdi.

4. Node'dagi stack trace

Node ham Chrome'dagi V8 dvigatelida ishlaydi, shuning uchun xato matnlari bir xil. Farq — ko'rinishda. savat.js:

js
const menyu = {
  osh: { narx: 35000 },
  manti: { narx: 30000 },
};
let jami = 0;

function narxniOl(taom) {
  return menyu[taom].narx;
}

function savatgaQosh(taom) {
  jami += narxniOl(taom);
}

savatgaQosh("osh");
savatgaQosh("Manti");
console.log(jami);

node savat.js — Node 24 terminalda (C:\... — yo'l qisqartirildi):

text
C:\...\09\savat.js:8
  return menyu[taom].narx;
                     ^

TypeError: Cannot read properties of undefined (reading 'narx')
    at narxniOl (C:\...\09\savat.js:8:22)
    at savatgaQosh (C:\...\09\savat.js:12:11)
    at Object.<anonymous> (C:\...\09\savat.js:16:1)
    at Module._compile (node:internal/modules/cjs/loader:1929:14)
    at Object..js (node:internal/modules/cjs/loader:2060:10)
    at Module.load (node:internal/modules/cjs/loader:1651:32)
    at Module._load (node:internal/modules/cjs/loader:1443:12)
    at wrapModuleLoad (node:internal/modules/cjs/loader:261:19)
    at Module.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:154:5)
    at node:internal/main/run_main_module:33:47

Node.js v24.21.0

"Manti" katta harf bilan — menyuda bunday kalit yo'q, menyu["Manti"] — undefined. Ikki muhitni solishtiramiz:

Chrome Node
Boshida Uncaught Fayl yo'li, kod qatori va ^
Fayl manzili http://…/asosiy.js C:\…\savat.js
Faylning o'zi at http://…:8:9 at Object.<anonymous>
Begona qatorlar <anonymous> (brauzer kodi) node:internal/…
Xatodan keyin Sahifa ishlashda davom etadi Butun dastur to'xtaydi

Oxirgi qator eng muhim farq. Node'da console.log(jami) umuman ishlamadi — dastur yiqildi. Brauzerda esa faqat bitta ish to'xtaydi, boshqa tugmalar ishlayveradi. Shuning uchun brauzerdagi xato "ko'zdan qochishi" oson: sahifa tirik, konsolni esa hech kim ochmagan.

5. SyntaxError: kod umuman ishlamaganda

Bu safar fayl oxirida } unutilgan:

js
function salomBer() {
  console.log("Salom");

salomBer();
html
<p>Sahifa chizildi, skript esa ishlamadi.</p>
<script>
  function salomBer() {
    console.log("Salom");

  salomBer();
</script>

Konsolda:

text
Uncaught SyntaxError: Unexpected end of input

Tarjimasi: "kutilmagan kirish oxiri" — ya'ni JavaScript yana kod kutayotgan edi, fayl esa tugab qoldi. Faylda bo'lsa, DevTools manzil sifatida asosiy.js:5:1 ni beradi: 4 qatorli faylning 5-qatori, ya'ni fayl oxiridan keyingi joy.

Ikki muhim fakt:

  • Stack trace yo'q. Kod bajarilmadi — chaqiruvlar ham bo'lmadi. Shuning uchun Salom ham chiqmadi: SyntaxError da birorta qator ishlamaydi (Xato xabarini o'qish).
  • Manzil — sezilgan joy, xato joyi emas. Unexpected end of input ko'rsangiz, yuqoriga qarab yopilmagan {, ( yoki qo'shtirnoq qidiring. VS Code qavs juftini rang bilan ko'rsatadi — bu qidiruvni tezlashtiradi.

Ammo SyntaxError faqat yozuvda bo'lmaydi. Ba'zi funksiyalar ish paytida satrni "o'qiydi" va uni tushunolmasa, xuddi shu nomli xato beradi: JSON.parse noto'g'ri JSON'ni, querySelector noto'g'ri selektorni ko'rganda. Ularda stack trace bor, chunki kod ishlab turgan edi. Misollari xatolar lug'atida.

6. Xato turlari lug'ati

6.1 Oltita tur

Tur Qachon chiqadi Birinchi nimani tekshirish
SyntaxError Yozuv qoidasi buzilgan yoki satr tahlil qilinmadi Qavs, qo'shtirnoq; JSON, selektor matni
ReferenceError Bunday nom yo'q yoki hali tayyor emas Imlo, katta-kichik harf, e'lon joyi
TypeError Qiymat bu ishga yaramaydi null/undefined qayerdan keldi
RangeError Son ruxsat etilgan oraliqdan tashqarida Uzunlik, chuqurlik, argument
URIError Manzilni kodlash/ochish buzildi % belgisi va URL qismlari
AggregateError Bir nechta xato bittaga yig'ilgan Ichidagi errors ro'yxati

Yettinchisi — EvalError — tarixiy tur, zamonaviy JavaScript uni deyarli chiqarmaydi. Brauzerda yana bir oila bor: DOMException — DOM metodlarining xatolari. Ularning nomi SyntaxError, InvalidCharacterError kabi bo'ladi.

Quyidagi xabarlar Node 24 da ishga tushirib olingan, DOM xatolari — Chrome 154 da. Ikkalasida dvigatel bitta (V8), shuning uchun matn bir xil — siz ham aynan shuni ko'rasiz.

6.2 SyntaxError

text
SyntaxError: Unexpected token ')'
SyntaxError: missing ) after argument list
SyntaxError: Invalid or unexpected token
SyntaxError: Identifier 'narx' has already been declared
SyntaxError: Unexpected token 'o', "osh" is not valid JSON
SyntaxError: Unexpected end of JSON input
  • Unexpected token ')' — "kutilmagan belgi )": ortiqcha yoki noto'g'ri joydagi qavs.
  • missing ) after argument list — "argumentlardan keyin ) yo'q": chaqiruv qavsi yopilmagan.
  • Invalid or unexpected token — "noto'g'ri belgi": ko'pincha yopilmagan qo'shtirnoq ("salom;) yoki Word'dan ko'chgan "jingalak" qo'shtirnoq.
  • Identifier … has already been declared — "bu nom allaqachon e'lon qilingan": bitta let narx ikki marta.
  • … is not valid JSON — JSON.parse ga JSON bo'lmagan matn berildi (nusxalash darsida ko'rgansiz). Bo'sh satr bo'lsa — Unexpected end of JSON input.

6.3 ReferenceError

text
ReferenceError: narx is not defined
ReferenceError: Cannot access 'narx' before initialization
  • is not defined — "aniqlanmagan": nom yo'q. Imloni tekshiring: Narx va narx — ikki xil nom.
  • Cannot access … before initialization — "boshlang'ich qiymat berilishidan oldin murojaat qilib bo'lmaydi": let/const o'zgaruvchi e'lon qatoridan oldin ishlatildi. Bu hodisaning nomi va ichki sababi — TDZ darsida.

6.4 TypeError — eng ko'p uchraydigani

text
TypeError: Cannot read properties of null (reading 'addEventListener')
TypeError: Cannot read properties of undefined (reading 'narx')
TypeError: menyu.addEventListner is not a function
TypeError: narxlar is not iterable
TypeError: Assignment to constant variable.
TypeError: Cannot destructure property 'nom' of 'null' as it is null.
  • Cannot read properties of null (reading 'X') — "null ning X xususiyatini o'qib bo'lmaydi". DOM'da 90% holatda: querySelector element topmagan. Selektorni va skript qachon ishlashini tekshiring (brauzer muhiti).
  • … of undefined — xuddi shu, lekin qiymat undefined: obyektda bunday kalit yo'q, massivda bunday indeks yo'q, find hech narsa topmagan yoki dataset da atribut yo'q. Farqni eslab qoling: null — ko'pincha "element topilmadi", undefined — "bunday kalit yoki element yo'q".
  • X is not a function — "X funksiya emas": nomda xato (addEventListner) yoki metod bu turda yo'q.
  • is not iterable — "aylanib bo'lmaydi": for...of ga obyekt yoki null berildi.
  • Assignment to constant variable. — const ga qayta qiymat berildi.
  • Cannot destructure … — null dan destructuring qilindi (obyekt destructuring).

DOM bilan ishlaganda uchta xato ayniqsa ko'p uchraydi. Uchalasi bitta oynada — har <script> alohida ishlaydi, shuning uchun biri yiqilsa ham keyingisi bajariladi:

html
<ul>
  <li class="taom">Osh</li>
  <li class="taom">Manti</li>
</ul>
<script>
  const taomlar = document.getElementsByClassName("taom");
  taomlar.forEach((taom) => console.log(taom));
</script>
<script>
  document.querySelector("#1-stol");
</script>
<script>
  document.querySelector("li").classList.add("taom faol");
</script>

Konsolda:

text
Uncaught TypeError: taomlar.forEach is not a function
Uncaught SyntaxError: Failed to execute 'querySelector' on 'Document': '#1-stol' is not a valid selector.
Uncaught InvalidCharacterError: Failed to execute 'add' on 'DOMTokenList': The token provided ('taom faol') contains HTML space characters, which are not valid in tokens.
  1. HTMLCollection da forEach yo'q (Elementlarni tanlash). Tuzatish: querySelectorAll yoki for...of.
  2. "'#1-stol' — yaroqli selektor emas". CSS'da id selektori raqam bilan boshlana olmaydi. Bu DOMException, lekin nomi SyntaxError: selektor matni tahlil qilinmadi.
  3. "Token HTML bo'sh joy belgilarini o'z ichiga oladi". classList.add ga bitta satrda ikki class berildi. To'g'risi: add("taom", "faol") (classList).

Failed to execute 'X' on 'Y' qolipini eslab qoling: "Y dagi X metodini bajarib bo'lmadi". Undan keyingi qism — sabab.

6.5 RangeError, URIError, AggregateError

text
RangeError: Maximum call stack size exceeded
RangeError: Invalid array length
RangeError: toFixed() digits argument must be between 0 and 100
URIError: URI malformed
  • Maximum call stack size exceeded — "chaqiruvlar steki to'ldi": funksiya o'zini to'xtovsiz chaqirdi (rekursiya). DOM'da ko'pincha: render ichidan yana render.
  • Invalid array length — massiv uzunligi manfiy yoki juda katta: new Array(-1).
  • toFixed() digits … — toFixed ga 0–100 dan tashqari son berildi.
  • URI malformed — "manzil buzilgan": decodeURIComponent("%") kabi, URL'dagi % dan keyin to'g'ri kod kelmagan (URL anatomiyasi).

AggregateError — "yig'ma xato": bir nechta xato bitta obyekt ichida, errors ro'yxatida. U parallel ishlarda chiqadi (Promise kombinatorlari) va keyingi bo'limda uni haqiqiy chiqishda ko'rasiz.

Tekshirib ko'ring: Cannot read properties of undefined (reading 'narx') va narx is not defined — farqi nimada?

Javob

Birinchisi TypeError: narx — xususiyat nomi, uni undefined qiymatdan o'qishga urinildi (taom.narx, taom esa undefined). Ikkinchisi ReferenceError: narx degan o'zgaruvchi umuman yo'q. Birinchida "chap tomondagi qiymat qayerdan keldi?" deb qidirasiz, ikkinchida — nomning imlosini va e'lon qilinganini tekshirasiz.

7. Sabablar zanjiri: cause

Ba'zan bitta xato boshqasining oqibati bo'ladi. Zamonaviy JavaScript'da xato o'z sababini cause xususiyatida saqlay oladi — va Node uni zanjir qilib chiqaradi.

Misol: Aziz Node'da lokal serverdan menyuni so'ramoqchi. fetch — serverdan ma'lumot so'raydigan funksiya, uni fetch asoslari darsida o'rganamiz. Bugun faqat xatosini o'qiymiz. Server esa ishga tushirilmagan:

js
fetch("http://localhost:4000/menyu");

Node 24 terminalda:

text
node:internal/process/promises:394
    triggerUncaughtException(err, true /* fromPromise */);
    ^

[TypeError: fetch failed] {
  [cause]: AggregateError [ECONNREFUSED]: 
      at internalConnectMultiple (node:net:1430:18)
      at afterConnectMultiple (node:net:2099:7) {
    code: 'ECONNREFUSED',
    [errors]: [
      Error: connect ECONNREFUSED ::1:4000
          at createConnectionError (node:net:2062:14)
          at afterConnectMultiple (node:net:2092:16) {
        errno: -4078,
        code: 'ECONNREFUSED',
        syscall: 'connect',
        address: '::1',
        port: 4000
      },
      Error: connect ECONNREFUSED 127.0.0.1:4000
          at createConnectionError (node:net:2062:14)
          at afterConnectMultiple (node:net:2092:16) {
        errno: -4078,
        code: 'ECONNREFUSED',
        syscall: 'connect',
        address: '127.0.0.1',
        port: 4000
      }
    ]
  }
}

Node.js v24.21.0

Qo'rqmang — uni ichkariga qarab, qavatma-qavat o'qiymiz:

  1. Tashqi xato: TypeError: fetch failed — "so'rov muvaffaqiyatsiz". Umumiy, sababi aytilmagan.
  2. [cause] — "sababi": AggregateError [ECONNREFUSED]. Ulanish rad etildi. AggregateError — chunki bir nechta urinish bo'lgan.
  3. [errors] — ikkala urinish: ::1:4000 va 127.0.0.1:4000. localhost ikki manzilga ega (IPv6 va IPv4), Node ikkalasini sinagan, ikkalasi ham rad etilgan.
  4. Ildiz sabab: 4000-portda hech kim tinglamayapti — server ishga tushirilmagan.

Qoida: zanjirda eng ichkaridagi xato ko'pincha eng aniq javob. Tashqi xato "nima buzildi", ichkisi "nega buzildi" deydi. ECONNREFUSED kabi kodlar (port darsi) qidiruvga berish uchun ham qulay. Eng tepadagi node:internal/… va triggerUncaughtException qatorlari — Node'ning ichki kodi, ular sizga kerak emas.

O'zingiz xatoga cause qo'shishni throw va Error obyekti darsida o'rganasiz.

8. Asinxron xato: "kim chaqirdi?" yo'qolganda

Taymerdan keyin ishlaydigan kod:

js
function eslat() {
  const xabar = document.querySelector("#eslatma");
  xabar.hidden = false;
}

setTimeout(eslat, 100);

Sahifada #eslatma yo'q. Chrome konsolida:

text
Uncaught TypeError: Cannot set properties of null (setting 'hidden')
    at eslat (http://127.0.0.1:5500/assets/js/asosiy.js:3:16)

Izda bitta qator! setTimeout ni 6-qator chaqirgan edi, lekin u yo'q. Sababi: eslat ni 100 ms dan keyin brauzer chaqirdi — o'sha paytda 6-qator allaqachon tugab bo'lgan. Hodisa tinglovchilarida ham shunday: zanjir doim brauzerda boshlanadi.

DevTools bu yo'qotishni qisman tiklaydi. Sources panelida Pause on uncaught exceptions ni yoqing (DevTools darsi) va sahifani yangilang. Pauza paytida Call Stack'da eslat ostida setTimeout (async) ajratgichi va undan keyin taymerni qo'ygan qator chiqadi. Bu — asinxron stack trace (async stack trace): "bu kodni kim rejalashtirgan" degan javob. Node'dagi asinxron izlar — Stack trace, source map va error.cause darsida.

9. Source map: siqilgan koddagi xato

Real saytga chiqadigan JavaScript odatda yig'iladi va siqiladi: bo'sh joylar olinadi, nomlar qisqaradi, hammasi bitta qatorga tushadi. Buni Vite yoki esbuild kabi vositalar qiladi — kursda alohida o'rganamiz, hozir bilish shart emas. Savat kodimizni esbuild bilan siqsak:

text
(()=>{var a=0;function n(){let t=document.querySelector("#jami");t.textContent=a}function e(t){a+=t,n()}var o=document.querySelectorAll("[data-narx]");for(let t of o)t.addEventListener("click",()=>{e(Number(t.dataset.narx))});})();

Xato endi shunday ko'rinadi:

text
Uncaught TypeError: Cannot set properties of null (setting 'textContent')
    at n (http://127.0.0.1:5500/assets/js/asosiy.min.js:1:79)
    at e (http://127.0.0.1:5500/assets/js/asosiy.min.js:1:101)
    at HTMLButtonElement.<anonymous> (http://127.0.0.1:5500/assets/js/asosiy.min.js:1:199)

n, e, 1:79 — bu bilan ishlab bo'lmaydi. Yechim — source map (manba xaritasi): "siqilgan koddagi har belgi asl faylning qaysi qatoridan kelgan" degan alohida fayl (asosiy.min.js.map). Siqilgan fayl oxirida unga havola turadi. DevTools xaritani topsa, stack trace va Sources'da asl asosiy.js ni ko'rsatadi. Batafsil — Source map'lar darsida.

10. console.trace va console.assert

Xato chiqmasa ham, "bu qatorga qaysi yo'l bilan keldim?" degan savol tug'iladi. console API darsida ikki yordamchini ko'rgansiz — endi ularni debugging asbobi sifatida ishlatamiz.

console.trace — xatosiz stack trace. Funksiya bir necha joydan chaqirilsa, qaysi biri hozir chaqirganini ko'rsatadi:

js
function narxniHisobla(narx, soni) {
  console.trace("narx hisoblanmoqda");
  return narx * soni;
}

function chekniChiqar() {
  console.log(narxniHisobla(35000, 2));
}

chekniChiqar();

Node 24 terminalda (boshi):

text
Trace: narx hisoblanmoqda
    at narxniHisobla (C:\...\09\trace.js:2:11)
    at chekniChiqar (C:\...\09\trace.js:7:15)
    at Object.<anonymous> (C:\...\09\trace.js:10:1)

Undan keyin node:internal qatorlari va 70000 keladi. Format xato izi bilan bir xil — faqat birinchi qatorda Trace: turibdi va dastur to'xtamaydi.

console.assert — "bunday bo'lishi shart" degan tekshiruv. Shart bajarilmasa, xabar chiqaradi:

js
const jami = 70000;
console.assert(jami > 100000, "jami 100 000 dan oshmadi");
console.assert(jami > 0, "bu xabar chiqmaydi");
console.log("dastur davom etdi");

Konsolda:

text
Assertion failed: jami 100 000 dan oshmadi
dastur davom etdi

Debuggingda u gipotezani tekshirishning qisqa yo'li: console.assert(narx > 0, "narx", narx) — narx musbat bo'lsa jim turadi, musbat bo'lmasa darhol chiqadi.

Diqqat: Darsdagi jonli oyna konsoli console.trace va console.assert ni ko'rsatmaydi. Ularni DevTools'da sinang: Chrome'da Assertion failed qizil xato sifatida chiqadi, ikkalasining ostida esa chaqiruvlar ro'yxati — funksiya nomi va fayl:qator havolasi bo'ladi.

11. Ko'p uchraydigan xatolar

11.1 Faqat birinchi qatorni o'qish

TypeError: Cannot read properties of null ni ko'rib, at qatorlariga qaramasdan kodni varaqlash.

Avval eng yuqoridagi o'z faylingiz qatori: fayl:qator. Havolani bosing — bir soniyada o'sha joydasiz.

11.2 Yiqilgan qatorni "tuzatish"

5-qatordagi jamiQator.textContent ni jamiQator?.textContent deb yozib, xatoni "yo'qotish". Xato yo'qoldi, jami esa ekranda hech qachon yangilanmaydi.

null qayerdan kelganini toping. Optional chaining (?.) — "bu yerda element bo'lmasligi normal" bo'lgan joy uchun, yashirish uchun emas.

11.3 Ikkinchi xatodan boshlash

Konsolda besh qator qizil — oxirgisini tuzatish.

Birinchisidan boshlang. Ko'pincha keyingilari uning oqibati: element topilmadi → u bilan bog'liq hamma narsa yiqildi.

11.4 Brauzer va kutubxona kodida qidirish

NodeList.forEach (<anonymous>) yoki node_modules/… qatoriga kirib, xatoni u yerdan izlash.

Bu qatorlar sizga yo'l ko'rsatadi, xolos. O'z faylingiz turgan qatorga qayting: begona kod odatda siz bergan noto'g'ri qiymat tufayli yiqiladi.

11.5 Xabarni o'z nomlaringiz bilan qidirish

Google'ga jamiQator.textContent null yozish — sizning nomlaringizni hech kim bilmaydi.

Umumiy qismni qo'shtirnoqda: "Cannot set properties of null" (samarali qidirish).

12. Mashqlar

1-mashq (oson): Turi va tarjimasi

Har xabar uchun xato turini va qisqa tarjimasini yozing, keyin birinchi nimani tekshirishni ayting.

  1. Uncaught ReferenceError: tugma is not defined
  2. Uncaught TypeError: forma.addEventListener is not a function
  3. Uncaught SyntaxError: Invalid or unexpected token
  4. Uncaught RangeError: Maximum call stack size exceeded
  5. Uncaught TypeError: Cannot read properties of null (reading 'value')
Yechim
# Turi Tarjima va birinchi tekshiruv
1 ReferenceError "tugma aniqlanmagan" — nomning imlosi va e'lon qilinganmi
2 TypeError "funksiya emas" — forma da nima bor? Ehtimol, element emas, boshqa qiymat
3 SyntaxError "noto'g'ri belgi" — yopilmagan qo'shtirnoq yoki jingalak qo'shtirnoq
4 RangeError "stek to'ldi" — o'zini to'xtovsiz chaqirayotgan funksiya
5 TypeError "null dan value ni o'qib bo'lmaydi" — maydon querySelector bilan topildimi

2-xabar haqida: querySelector topmasa null beradi va xato boshqacha bo'lardi (Cannot read properties of null). "is not a function" — demak forma da null emas, boshqa qiymat bor: masalan, forma o'zgaruvchisiga element o'rniga satr berilgan.

2-mashq (o'rta): Izni o'qing

«Bahor» saytida shunday xato chiqdi. Kod — «Nomsiz funksiyalar va brauzerning o'z kodi» bo'limidagi asosiy.js.

text
Uncaught TypeError: Cannot read properties of undefined (reading 'toUpperCase')
    at belgila (http://127.0.0.1:5500/assets/js/asosiy.js:4:36)
    at http://127.0.0.1:5500/assets/js/asosiy.js:9:3
    at NodeList.forEach (<anonymous>)
    at http://127.0.0.1:5500/assets/js/asosiy.js:8:9

Savollar: 1) qaysi funksiyada, qaysi qatorda yiqildi; 2) qaysi qatorlarni o'tkazib yuborasiz va nega; 3) undefined qaysi ifodadan keldi; 4) ikkita tuzatish varianti va qaysi biri qachon to'g'ri.

Yechim
  1. belgila, 4-qator, 36-ustun — .toUpperCase() chaqirilgan joy.
  2. NodeList.forEach (<anonymous>) — brauzerning o'z kodi. 9:3 va 8:9 — o'z faylimiz, lekin ular faqat "qanday yetib kelindi" yo'li: forEach dagi nomsiz strelka → belgila.
  3. taom.dataset.holat — data-holat atributi yo'q li da undefined (dataset).
  4. Agar har taomda holat bo'lishi shart bo'lsa — HTML'ni tuzating (atribut yetishmaydi). Agar holat ixtiyoriy bo'lsa — kodni tuzating: atribut yo'q bo'lsa, yozuv qo'shmang (erta qaytish):
js
function belgila(taom) {
  if (taom.dataset.holat === undefined) {
    return;
  }
  const holat = taom.dataset.holat.toUpperCase();
  taom.textContent += ` (${holat})`;
}

Qaysi biri to'g'riligini kod emas, qoida hal qiladi — Jasur akadan so'rash kerak: har taomda holat bormi?

3-mashq (qiyin): Stol tanlash

Bron sahifasida stolni tanlasangiz, uning o'rinlari soni chiqishi kerak. Istalgan tugmani bosing va konsoldagi xabarni o'qing. Xato qayerda yiqilganini va aybdor qiymat qayerda tug'ilganini toping, keyin tuzating. Ishora: xabarni o'qigach, «Tahrirlab ko'rish» bilan stolniTanla ichiga console.log(id, typeof id) qo'yib ko'ring.

html
<p>Stolni tanlang:</p>
<button type="button" data-id="1">1-stol</button>
<button type="button" data-id="2">2-stol</button>
<button type="button" data-id="3">3-stol</button>
<p id="stol-haqida">Stol tanlanmagan</p>
<script>
  const stollar = [
    { id: 1, joylar: 4 },
    { id: 2, joylar: 6 },
    { id: 3, joylar: 10 },
  ];
  const haqida = document.querySelector("#stol-haqida");

  function stolniKorsat(stol) {
    haqida.textContent = `${stol.id}-stol: ${stol.joylar} o'rin`;
  }

  function stolniTanla(id) {
    const stol = stollar.find((s) => s.id === id);
    stolniKorsat(stol);
  }

  for (const tugma of document.querySelectorAll("[data-id]")) {
    tugma.addEventListener("click", () => {
      stolniTanla(tugma.dataset.id);
    });
  }
</script>
Yechim

Jonli oynada: Uncaught TypeError: Cannot read properties of undefined (reading 'id'). Xuddi shu kod asosiy.js faylida bo'lsa, Chrome to'liq izni beradi:

text
Uncaught TypeError: Cannot read properties of undefined (reading 'id')
    at stolniKorsat (http://127.0.0.1:5500/assets/js/asosiy.js:9:32)
    at stolniTanla (http://127.0.0.1:5500/assets/js/asosiy.js:14:3)
    at HTMLButtonElement.<anonymous> (http://127.0.0.1:5500/assets/js/asosiy.js:19:5)
  • Yiqilgan joy: stolniKorsat — stol.id o'qilganda, stol esa undefined.
  • Aybdor qiymat: bir qavat pastda, stolniTanla da tug'ilgan: find hech narsa topmagan. Nega? console.log(id, typeof id) → 1 string. dataset doim satr beradi, massivdagi id esa son. "1" === 1 — false (tenglik operatorlari).
  • Tuzatish — qiymat tug'ilgan joyda, bitta o'zgarish:
js
stolniTanla(Number(tugma.dataset.id));

Endi 3-stol bosilsa, "3-stol: 10 o'rin" chiqadi. Stack trace sizni stolniKorsat ga olib bordi, lekin tuzatish ikki qavat pastda bo'ldi. Iz — yo'l ko'rsatkich, javob emas.

4-mashq: Portfolio qadami — ataylab xato va uni iz bo'yicha topish

Xatoni o'zingiz yasab, uni faqat stack trace bo'yicha topish — eng yaxshi mashq. Keyin hammasini avvalgi holatiga qaytarasiz.

  1. sayt/assets/js/asosiy.js da joriyHavolaniBelgila funksiyasini toping (dataset dagi portfolio qadami). Undagi menyu.querySelectorAll("a") ni menyu.querySelectorAl("a") ga o'zgartiring — bitta l kam.
  2. Bosh sahifani Live Server'da oching. Konsoldagi xabarni ko'chirib, uch savolga javob yozing: turi va tarjimasi; qaysi funksiya, qaysi qator; bu funksiyani kim chaqirgan.
  3. Havolani bosib, Sources'da aynan o'sha qatorga o'ting.
  4. Sahifadagi boshqa JavaScript imkoniyatlarini sinang: mavzu tugmasi, telefon menyusi, forma tekshiruvi ishlayaptimi?
  5. Endi 404.html ni oching. Xato chiqadimi? Nega? (Ishora: o'tgan dars — takrorlash qadamlari qaysi sahifalarda ishlaydi.)
  6. Xatoni qaytaring va git diff bo'sh ekanini tekshiring. Bu mashqdan commit qilinmaydi — u faqat o'qish uchun.
Yechim

Bosh sahifada (qator raqamlari sizda boshqacha bo'ladi — asosiy.js ga qo'shgan kodingizga bog'liq):

text
Uncaught TypeError: menyu.querySelectorAl is not a function or its return value is not iterable
    at joriyHavolaniBelgila (http://127.0.0.1:5500/assets/js/asosiy.js:30:30)
    at http://127.0.0.1:5500/assets/js/asosiy.js:45:1
  • Turi TypeError. Tarjimasi: "menyu.querySelectorAl — funksiya emas yoki uning qaytargan qiymati aylanib bo'lmaydigan". Chaqiruv for...of ichida bo'lgani uchun V8 ikki ehtimolni birga aytyapti. Bizda birinchisi: elementda bunday metod yo'q.
  • Yiqilgan joy — joriyHavolaniBelgila, 30-qator (for qatori). Uni faylning o'zi chaqirgan (45-qatordagi joriyHavolaniBelgila()) — shuning uchun funksiya nomi yo'q, faqat manzil.
  • 4-qadam: bu chaqiruvdan keyin yozilgan hamma kod ishlamay qoldi — skript shu qatorda to'xtadi. Faylingizda mavzu tugmasi yoki forma kodi undan pastda bo'lsa, ular ham "o'chib" qoladi. Bitta xato butun faylni to'xtatishining amaliy namunasi.
  • 404.html da xato chiqmaydi: u yerda menyu yo'q, funksiya menyu === null tekshiruvidan keyin erta qaytadi va for ga yetmaydi. Demak, bu xatoni takrorlash retsepti: "menyusi bor sahifani oching". Faqat 404 da sinagan odam "hammasi ishlayapti" deb o'ylardi.

git diff bo'sh bo'lsa, hammasi avvalgidek. VS Code'da Ctrl + Z yoki terminalda git restore sayt/assets/js/asosiy.js (xatoni tuzatish 1) bilan qaytarsa bo'ladi.

13. Real ishda

  • Xato monitoringi. Foydalanuvchi brauzerida chiqqan xato dasturchiga ko'rinmaydi — u konsolni ochmaydi. Shuning uchun saytlarga xatolarni yig'ib, stack trace bilan yuboradigan xizmat ulanadi (masalan Sentry — kursda alohida o'rganamiz). Ular source map yordamida izni asl kodga qaytaradi (Production xatolari).
  • Xato xabari — savolning yarmi. Hamkasbga yoki issue'ga xatoni yozganda to'liq xabar va stack trace'ni matn qilib qo'ying, skrinshot emas — matnni qidirsa va ko'chirsa bo'ladi (yordam so'rash).
  • React va boshqa freymvorklar (keyingi qismlarda o'rganamiz) stack trace'ga o'z qatorlarini qo'shadi. Qoida o'zgarmaydi: o'z faylingizning eng yuqori qatorini toping.
  • Intervyu. "null va undefined xatolari farqi nima?", "stack trace'ni qanday o'qiysiz?", "source map nima?" — junior intervyularda tez-tez so'raladi.

Xulosa

  • Xato = turi + matni + izi (stack trace); Uncaught — hech kim ushlamagan.
  • Stack trace tepadan pastga: birinchi o'z faylingiz qatori — yiqilgan joy; aybdor qiymat ko'pincha undan oldin tug'iladi.
  • <anonymous> — nomsiz funksiya yoki brauzerning o'z kodi; node:internal, node_modules — o'tkaziladi.
  • Brauzerda xato bitta ishni to'xtatadi, Node'da — butun dasturni.
  • Turlar: SyntaxError — yozuv, ReferenceError — nom, TypeError — qiymat, RangeError — chegara, URIError — manzil, AggregateError — bir nechta xato.
  • cause zanjirida eng ichkaridagi xato — ildiz sabab; async izda chaqiruvchi yo'qoladi, siqilgan kodni source map tiklaydi.

Keyingi dars: Yakuniy loyiha: vanilla JS vazifalar ro'yxati — qismda o'rgangan hamma narsani bitta ilovada birlashtirasiz va xatolarni bugungi usullar bilan topasiz.

Manbalar

  • MDN: "JavaScript error reference" — developer.mozilla.org
  • MDN: "Error: cause", "AggregateError", "DOMException" — developer.mozilla.org
  • Chrome DevTools: "Console overview", "Debug original code instead of deployed with source maps" — developer.chrome.com/docs/devtools
  • Node.js: "Errors" — nodejs.org/api/errors.html
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Stack trace va JavaScript xato turlari: xato xabarini brauzerda va Node'da o'qish — IlmHamroh