Rozdíl mezi null a undefined v JavaScriptu

Před pár dny mi dorazil mail od Jakuba Vrány, ve kterém se mě ptal, jestli nevím, proč má JavaScript kromě hodnoty null ještě undefined. Protože si myslím, že má odpověď by mohla zajímat více lidí, rozhodl jsem se ji spolu s původním dotazem zveřejnit a budu rád, pokud ji případně v komentářích doplníte.

Dotaz

Tušíš, proč je v JavaScriptu jak hodnota null, tak undefined? Podle mě by se všude na místě null dalo používat undefined. Má nějaký smysl mít dvě speciální hodnoty?

Odpověď

Nějaký "oficiální" důvod jsem nikde nenašel. Ve specifikaci je sice popsáno chování, ale zdůvodnění existence chybí.

Osobně se domnívám, že jde hlavně o sémantický rozdíl.

Hodnotu undefined vrací konstrukce jazyka, když chtějí říct "nevím":

V podstatě jsou to situace, kdy by jiné jazyky vrátily chybu. Kdyby se všechny situace, kdy se vrací undefined, nahradily vyvoláním chyby, JavaScript by dál fungoval a byl konzistentní, jen by byl o něco striktnější.

Hodnota undefined je tedy taková spíš systémová záležitost; prostředek, jak jazyk učinit volnější. Nemyslím, že by programátor měl vůbec kdy napsat výraz, který by undefined vracel.

Hodnota null je naopak hodnota, u které se využití uživatelem očekává – jazyk sám ji používá minimálně. Slouží především k tomu, aby uživatel měl jak vyjádřit "nezadáno".

Otázkou je, zda oddělení null a undefined nepřináší víc problémů než užitku. Pokud by se tyto hodnoty sloučily a všude, kde se dnes vrací undefined, by se vracelo null, mělo by za důsledek neodlišitelnost některých situací:

Na první pohled se zdá, že to jsou docela vážné problémy, ale zkušenost z jiných jazyků ukazuje, že zdaleka tak vážné nejsou. Například v jazyce Ruby mají nedefinované instanční proměnné hodnotu nil (ekvivalent null) a tuto hodnotu vrací také neúspěšný přístup k položce v hash tabulce nebo přístup k položce pole, co je out-of-range. Podobně vrací nil metoda bez explicitního return. Nezdá se, že by toto někomu vadilo (lidi na Ruby kritizují hodně věcí, ale tohle ne).

Toť asi vše, co jsem k tomuto tématu schopen říct.

Jan 12, 2009 – 20:54

Comments

Botanicus
Diky za clanek, Davide. Oddeleni undefined a null mi prijde jako rozumna zalezitost. Nestezuju si, ze to Ruby nema, nicmene uz jsem narazil na situace, kdy by se to hodilo. Napriklad u ORM. Mam treba model Invitation, ktery ma column message. Message ma nejakou defaultni hodnotu, ja ji chci nastavit na nil, ktre mi prijde v params. ORM si ale mysli to nebylo vyplneno a ze ma pouzit default, coz taky udela. Totez pri explicitnim invitation.message = nil. Dela to tusim jak ActiveRecord, tak DataMapper. Nejsem si uplne jist zda se tak chovaji oba (a kdyztak, tak ktery), ale asi jo. Samozrejme je to "feature" konkretniho softu, nicmene kdyby invitation.message = nil znamenala prazdnou hodnotu a invitation.message = undefined nedefinovanou hodnotu (pouzije se default value), byl by zde prostor pro logictejsi chovani techto ORM.
David Majda
[1] Myslím, že chceš trochu něco jiného, než undefined. V tvém příkladu je problém v tom, že hodnota z oboru hodnot atributu se používá zároveň jako indikátor speciálnícho chování (použití defaultu), čímž ji pak nemůžeš použít pro její původní účel. Řešení by bylo použít v ORM jako indikátor speciálního chování hodnotu mimo obor hodnot všech atributů (v Ruby třeba :default nebo nějaký speciální singleton Default).

Použití undefined by v tomto případě nebylo konzistentní s mou tezí o tom, že kdyby se všechny všechny situace, kdy se vrací undefined, nahradily vyvoláním chyby, nestalo by se nic zásadního kromě zpřísnění jazyka. Pro mě tahle teze v podstatě definuje sémantiku undefined (= hodnota vyhozená místo chyby při nesmyslné operaci) a zatím jsem nenarazil na nic, co by jí v JavaScriptu odporovalo.
Martin Hassman
"Jaká je hodnota nedefinované proměnné? Nevím."

Tenhle případ vrátí chybu (na rozdíl od těch ostatních případů, co uvádíš, což je docela zajímavá - byť asi žádoucí - nekonzistence).

Pro dokonalé zmatení lze otevřít Flanagana kapitolu 4.3.2 "Nedefinovaná a nepřiřazená" (v originále "Undefined Versus Unassigned"), kde Flanagan vysvětluje, že v JavaScriptu existují dva typy nedefinovaných (undefined) proměnných (ještě v tom nemáte tom terminologický zmatek? 8-).

Ta první nedefinovaná proměnná prostě nebyla nikdy deklarovaná (to je ta, jejíž přečtení vrátí chybu), ta druhá je ta, co byla deklarovaná ale nebyla definovaná a má regulérní hodnotu undefined.

Shrnuto: Deklarované nedefinované proměnné v JavaScriptu nemají chybu!
ToM
ToM
Ono je to celkem logicky:)
var neco; // deklarovany ale undefined
alert(neco);
nevrati chybu, ale
alert(necoJinyhoDriveNedefinovanyho) // nedeklarovany udefined
ji vrati.
Prijde me to spravne, pokud to spravne chapu:)

Add comment

It is not possible to add comments to posts older than one month.