Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grafomanský výlev na téma chybových hlášek #784

Open
jficz opened this issue May 15, 2024 · 2 comments
Open

Grafomanský výlev na téma chybových hlášek #784

jficz opened this issue May 15, 2024 · 2 comments

Comments

@jficz
Copy link
Contributor

jficz commented May 15, 2024

Můj trochu delší příspěvek na slacku. Dávám sem, aby se to nezmizelo, můžeme z toho třeba někdy časem vyextrahovat něco přímo do lekce.


index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
...

TypeError velmi obecně naznačuje, že někde pravděpodobně nesedí typy proměnných. To je první indicie, která nás může navést správným směrem, byť zrovna v Javascriptu je chyba typu TypeError spíš zavádějící, než užitečná.

Naštěstí se tu chybu snaží vysvětlit hned v další větě: Cannot read properties of <něco>:

Properties mají jen objekty. Například když máme objekt person = { name: "Blanka", age: "21" }, tak name a age jsou "properties" objektu person. Hláška Cannot read properties of <něco> říká, že se v kódu snažíš přistoupit k property, kterou to něco mít nemůže, což speciálně v Javascriptu pravděpodobně znamená, že to něco neexistuje.

A to je i náš případ, protože to něco je ve skutečnosti undefined. Kdyby ta hláška skončila tady, tak by to pro nás zas tak užitečné nebylo, protože nevíme, co přesně z toho řádku je undefined a tak tu máme poslední nápovědu, text v závorce: (reading 'add'). Tím nám říká, že ta property, kterou nemůže přečíst, se jmenuje add.

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
^^^^^^^^^ 
|_______|--- jméno souboru, kde je chyba


index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
          ^^
          ||--- řádek v souboru, kde je chyba


index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
             ^^^^^^^^^^^^^^^^^^
             |________________|--- typ/kategorie chyby
          

index.jsx:18 Uncaught TypeError: Cannot read properties of undefined (reading 'add')
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     konkrétní chybová hláška ---|_________________________________________________|

A dál to můžeme rozebrat takhle:

Uncaught TypeError === nesedí typy proměnných. V Javascriptu bohužel trochu matoucí. K pochopení je nutné přečíst si celou chybovou hlášku.

Chybová hláška je

Cannot read properties of undefined (reading 'add')
^^^^^^^^^^^^^^^^^^^^^^^^^
|_______________________|--- popis konkrétního problému (`nemůžu přečíst (nějakou) property`)


Cannot read properties of undefined (reading 'add')
                          ^^^^^^^^^
                          |_______|--- "tohle je ta věc, u který nemůžu přečíst property"


Cannot read properties of undefined (reading 'add')
                                     ^^^^^^^ ^^^^^
                                     |_____|+|___|--- property, kterou se snažím přečíst, se jmenuje 'add'

Abychom pak mohli zanalyzovat tu konkrétní chybu, musíme vycházet z těhle informací.

Víme soubor (index.jsx) a řádek (18), tak se tam podíváme. Pravděpodobně tam je tohle:

  ? bulb.classList.add('bulb--on')

Teď už budeme muset aplikovat nějaké znalosti a zkušenosti. A dbát na dobré rady zkušenějších. Jedna taková dobrá rada je "přečti si tu chybovou hlášku vždycky nejdřív úplně celou do konce".

Uncaught TypeError je divná věc, které nerozumíme a nic moc nám sama o sobě neřekneme, budeme tedy číst dál.

Cannot read property of undefined už nám může dávát trochu smysl, protože víme co je property a tušíme, co je undefined. Na tom řádku (na první pohled) vidíme dvě věci, co můžou být property, classList a add, ale nevidíme tam žádný undefined.

Čteme dál: (reading 'add')

A jsme doma! Teď už je jasné, že k chybě došlo při pokusu o "načtení" property add, protože to něco, z čeho se tu property snažíme načíst, je undefined. My se tady to add snažíme načíst (přesněji v tomhle případě "zavolat", protože je to funkce) z bulb.classList. To může znamenat jen jednu věc - že bulb.classList je undefined.

Už ale nevíme proč je undefined. S tím nám bohužel ta chybová hláška vůbec nijak nepomůže. Na to už budeme muset zapojit šedou kůru, fantazii, znalosti a zkušenosti.

Víme, že bulb je něco, co jsme si sami vytvořili - nejlepší je tedy začít tam, kde ten bulb vzniká.

Proč rovnou celý bulb a proč neřešíme bulb.classList? (nejméně) ze tří důvodů:

  1. bulb jsme si vytvořili my, je tedy zdaleka nejpravděpodobnější, že k nějaké chybě došlo při vytváření
  2. classList je property, o které víme že ji ten bulb musí mít, pokud je vytvořen správně (samozřejmě po tom, co jsme si důkladně zkontrolovali překlepy 😉 )
  3. ze zkušenosti časem budeme vědět, že tahle konkrétní chyba znamená, že bulb sice (v nějaké formě) existuje, ale bulb.classList už ne, což je v rozporu s bodem 2 a prakticky potvrzuje bod 1

To nám poměrně jasně naznačuje, že v bulb máme něco jiného, než co tam předpokládme. Konkrétně předpokládáme, že tam máme nějaký element. Každý element má property classList, náš bulb ale žádný classList nemá. Co s tím?

Podívejme se, jak bulb vzniká:

const bulb = document.querySelectorAll('.bulb');

Tady by nás mělo trknout, že děláme querySelectorAll(), který, už podle názvu, pravděpodobně bude vracet víc elementů najednou. Pokud si to z hlavy nepamatujeme*, podíváme se do dokumentace, kde se (mimo jiné) říká, že querySelectorAll() vrací pole elementů (array of elements), tudíž je jasné, že v proměnné bulb nemáme element, ale pole. A pole nemá property classList.

Jak to opravit? To už záleží na tom, čeho chceme dosánout. V tomhle případě chceme skutečně zpracovat všechny žárovky, tudíž chyba je primárně na řádku 18 (ale zároveň by bylo fajn tu proměnnou přejmenovat na bulbs) a musíme ji opravit tam. Pravěpodobně nějakým cyklem (např. forEach).

A po tom, co provedeme celou tuhle poměrně náročnou analýzu a syntézu, zjistíme, že to vlastně máme udělat úplně jinak a celý kód zahodíme. Vitejte ve světě programování! :)

*) nikdo po vás nikdy nebude chtít, abyste si všechno pamatovaly. Mnohem užitečnější je umět si informace najít

@podlomar
Copy link
Collaborator

Kubo, pojď to napsat jako článek na blog Kódím.cz

@jficz
Copy link
Contributor Author

jficz commented May 17, 2024

dobrej nápad :) okej, zkusim to nějak učesat a zgeneralizovat

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants