undefined i null w JavaScript oznaczają „brak wartości”, ale w różny sposób: undefined to brak przypisania (domyślna wartość nadawana przez silnik języka), a null to świadomie przypisana pusta wartość przez programistę.
Zrozumienie tej różnicy wpływa nie tylko na poprawność kodu, ale też na dostępność — decyduje, co trafi do DOM i do technologii asystujących.
Szybkie definicje
undefined — zmienna została zadeklarowana, ale nie przypisano jej żadnej wartości. To domyślna wartość nadawana przez silnik języka.
Najczęstsze przypadki, kiedy otrzymasz undefined to:
- nowo zadeklarowane zmienne bez inicjalizacji,
- parametry funkcji, które nie zostały przekazane,
- nieistniejące właściwości obiektów.
null — świadomie przypisana „pusta” wartość, zwykle oznaczająca brak obiektu lub brak aktualnej wartości. JavaScript nigdy sam z siebie nie przypisze null — to zawsze decyzja programisty.
null reprezentuje celowo ustawioną „pustkę”, a undefined — całkowity brak przypisania.
Krótkie porównanie — tabela
Dla szybkiego zestawienia kluczowych różnic zobacz poniższą tabelę:
| Cecha | undefined |
null |
|---|---|---|
| Kto nadaje wartość | Nadaje silnik JS automatycznie | Programista przypisuje świadomie |
| Znaczenie | „Nie zainicjalizowano”, „brak przypisania” | „Celowy brak wartości/obiektu” |
Typ wg typeof |
"undefined" |
"object" — historyczny błąd |
| Występowanie | Domyślna wartość zmiennych, argumentów, właściwości | Tylko po ręcznym przypisaniu lub z API/bazy danych |
Relacja luźna == |
undefined == null → true |
null == undefined → true |
Relacja ścisła === |
undefined === undefined → true |
null === null → true |
Dla Number(...) |
Number(undefined) → NaN |
Number(null) → 0 |
W kontekście logicznym if |
Wartość falsy | Wartość falsy |
| Rekomendowane użycie | „Systemowy brak inicjalizacji” | „Biznesowy brak wartości” — świadomy stan |
Skąd bierze się undefined?
Niezainicjalizowana zmienna
Jeśli zadeklarujesz zmienną bez nadania jej wartości, otrzyma undefined:
let count;
console.log(count); // undefined
Dotyczy to wszystkich deklaracji: let, const i var.
Pominięty parametr funkcji
Parametr, którego nie przekażesz przy wywołaniu funkcji, będzie miał wartość undefined:
function greet(name) {
console.log('Cześć, ' + name);
}
greet(); // name === undefined
Nieistniejąca właściwość obiektu
Dostęp do właściwości, której nie ma w obiekcie, zwraca undefined:
const user = { name: 'Anna' };
console.log(user.age); // undefined
Element tablicy bez wartości / poza zakresem
Odwołanie do elementu tablicy, który nie istnieje, również zwróci undefined:
const arr = [];
console.log(arr[10]); // undefined
Funkcja bez return
Funkcja, która nie zwraca jawnie wartości, domyślnie zwraca undefined:
function logMessage(msg) {
console.log(msg);
}
const result = logMessage('Cześć');
console.log(result); // undefined
Co oznacza null i po co w ogóle istnieje?
Świadoma decyzja programisty
null to wartość, którą programista przypisuje ręcznie, aby zaznaczyć: „tu jest celowo pusto”.
let selectedUser = null; // na razie nic nie wybrano
// później w kodzie:
selectedUser = { id: 1, name: 'Anna' };
JavaScript nie przypisze null automatycznie; jeśli widzisz null w zmiennej, to znaczy, że ktoś w kodzie ustawił go celowo.
Typowe zastosowania null
Poniżej kilka częstych zastosowań null w aplikacjach:
- „puste miejsce” na obiekt – np. bieżący użytkownik, aktywny element UI;
let activeModal = null; // żadne okno modalne nie jest otwarte
- brak wyniku – np. wyszukiwanie nic nie znalazło;
function findUser(id) {
const user = users.find(u => u.id === id);
return user ?? null; // brak wyniku → null
}
- wartość jeszcze niezaładowana (np. z API).
let profile = null; // jeszcze nie wiemy
let isLoading = true;
fetch('/api/profile')
.then(res => res.json())
.then(data => {
profile = data;
isLoading = false;
});
null często oznacza: wartość powinna istnieć, ale na razie jej nie ma lub nie została znaleziona.
undefined, null i „undeclared” — trzy różne sytuacje
Jest też trzeci przypadek: undeclared — zmienna w ogóle nie została zadeklarowana.
console.log(x); // ReferenceError: x is not defined
Różnice między trzema stanami są następujące:
undefined— zmienna istnieje (była zadeklarowana), ale nie ma przypisanej wartości,null— zmienna istnieje i ma świadomie przypisaną pustą wartość,- undeclared — zmienna nie została zadeklarowana; próba użycia kończy się błędem czasu wykonania.
Przykład, który pokazuje wszystkie trzy stany w praktyce:
let a; // zadeklarowana, nie zainicjalizowana
let b = null; // zadeklarowana, celowo pusta
// c — w ogóle nie istnieje
console.log(a); // undefined
console.log(b); // null
console.log(c); // ReferenceError
Jak działają porównania undefined i null?
Luźne porównanie ==
Specyfikacja JavaScript definiuje, że tylko null i undefined są sobie nawzajem równe przy ==:
null == undefined; // true
null == 0; // false
undefined == 0; // false
Stąd idiom:
if (value == null) {
// wejdziemy tu, gdy value jest null LUB undefined
}
To świadomy, skrócony sposób na sprawdzenie, czy wartość jest null lub undefined.
Ścisłe porównanie ===
Przy ścisłym porównaniu musi zgadzać się również typ:
null === undefined; // false
null === null; // true
undefined === undefined; // true
Używając ===, nigdy nie pomylisz null z undefined.
Zachowanie w instrukcji if (wartości „falsy”)
Zarówno null, jak i undefined są wartościami falsy (traktowane jak fałsz w kontekście logicznym):
if (!value) {
// wykona się dla: null, undefined, 0, '', false, NaN
}
To wygodne, ale bywa źródłem błędów — jeśli chcesz odróżnić pusty string ('') od null/undefined, sama negacja !value nie wystarczy.
Konwersja do liczb
Przy rzutowaniu na liczbę różnice są istotne:
Number(null); // 0
Number(undefined); // NaN
null konwertuje się do 0, a undefined do NaN (Not-a-Number). W obliczeniach może to prowadzić do subtelnych błędów:
const a = null;
const b = undefined;
console.log(a + 5); // 5 (0 + 5)
console.log(b + 5); // NaN
typeof null — słynna „wada” JavaScript
Sprawdzenie typów pokazuje pewną niespójność:
typeof undefined; // "undefined"
typeof null; // "object"
undefined ma swój własny typ prymitywny undefined. Z kolei null zwraca "object" — to historyczny błąd, którego nie naprawiono ze względu na kompatybilność.
W praktyce, aby sprawdzić undefined, użyj:
typeof value === 'undefined'
Natomiast, aby sprawdzić null, stosuj:
value === null
Dobre praktyki: kiedy używać undefined, a kiedy null?
Rekomendowany podział ról
undefined — zostaw je silnikowi JavaScript. Nie przypisuj undefined ręcznie (poza bardzo specyficznymi przypadkami). Traktuj je jako sygnał: „ta rzecz nie została jeszcze zainicjalizowana/przekazana/znaleziona”.
null — używaj świadomie w logice biznesowej, gdy chcesz zaznaczyć celowy brak wartości lub kiedy wartość powinna istnieć, ale „jeszcze nie” (np. przed załadowaniem danych) czy gdy czegoś nie znaleziono.
Przykładowy wzorzec w aplikacji webowej
Poniższy fragment pokazuje rozdzielenie stanów: brak danych, ładowanie, błąd:
// Stan widoku profilu użytkownika
let profile = null; // brak danych (jeszcze nie pobrane lub nie znaleziono)
let isLoading = false;
let error = null;
// Ładowanie danych
function loadProfile() {
isLoading = true;
error = null;
fetch('/api/profile')
.then(res => res.json())
.then(data => {
profile = data; // konkretny obiekt
})
.catch(err => {
error = err; // obiekt błędu
})
.finally(() => {
isLoading = false;
});
}
null oznacza: „na razie brak wartości/błędu, ale jest na nie miejsce”. undefined może pojawić się np. gdy backend nie przekaże jakiegoś pola w JSON — to sygnał, że w ogóle go nie określono.
Jak poprawnie sprawdzać null i undefined?
Sprawdzenie obu na raz
Gdy chcesz uznać null i undefined za równoważne „brak wartości”, możesz użyć luźnego porównania:
if (value == null) {
// value jest null LUB undefined
}
Alternatywnie skorzystaj z operatora „koalescencji nullish” ??:
const label = value ?? 'Domyślna wartość';
W tym wypadku label przyjmie domyślną wartość tylko wtedy, gdy value jest null lub undefined, ale nie wtedy, gdy jest np. pustym stringiem.
Sprawdzenie wyłącznie null
Gdy potrzebujesz wykryć dokładnie null (a nie undefined):
if (value === null) {
// dokładnie null, nie undefined
}
To przydatne, gdy undefined oznacza „systemowo: brak danych”, a null — „biznesowo: nie znaleziono, brak, usunięto”.
Sprawdzenie wyłącznie undefined
Gdy chcesz upewnić się, że wartość nie została w ogóle przekazana/zainicjalizowana:
if (typeof value === 'undefined') {
// wartość nie została zainicjalizowana lub argument nie został przekazany
}
To podejście jest odporne na ewentualne cienie zmiennych o nazwie undefined.
Typowe błędy z undefined i null (szczególnie w UI)
Wyświetlanie „undefined” lub „null” w interfejsie
Bez obróbki danych łatwo wstawić do DOM literalny tekst „undefined”/„null”:
const user = {};
const name = user.name; // undefined
document.querySelector('#name').textContent = `Użytkownik: ${name}`;
// W UI: "Użytkownik: undefined"
To częsty błąd. Zamiast tego użyj wartości zastępczej:
const name = user.name ?? 'Nieznany użytkownik';
W kontekście dostępności czytnik ekranu odczyta „undefined/null” dosłownie — lepiej dostarczyć sensowny tekst („Nieznany użytkownik”, „Brak danych”).
Operacje na undefined w obliczeniach
undefined w wyrażeniach arytmetycznych prowadzi do NaN, co może skutkować mylącymi wynikami w UI (np. „NaN zł”):
const price = undefined;
const tax = 0.23;
const total = price * (1 + tax); // NaN
Bezpieczniej ustalić domyślną liczbę:
const price = data.price ?? 0;
Destrukturyzacja z niepewnych źródeł
Destrukturyzacja z null/undefined kończy się błędem:
const user = null;
// const { name } = user;
// TypeError: Cannot destructure property 'name' of 'user' as it is null.
Dodaj zabezpieczenie lub domyślne wartości:
const user = null;
const { name = 'Anonim' } = user ?? {};
undefined i null a dostępność (a11y)
Różnica między tymi wartościami wpływa na to, co finalnie trafi do DOM i czytników ekranu.
Atrybuty ARIA i tekst alternatywny
Poniższy kod może wstawić do atrybutu literalne „undefined/null” — zależnie od środowiska:
const label = product.name; // może być undefined, null albo string
button.setAttribute('aria-label', label);
Bezpieczniejszym wzorcem jest ustawienie wartości zastępczej i ewentualne usunięcie atrybutu:
const label = product.name ?? 'Zobacz szczegóły produktu';
if (label) {
button.setAttribute('aria-label', label);
} else {
button.removeAttribute('aria-label');
}
Operator ?? chroni przed null/undefined, a dodatkowa walidacja zapobiega pustym atrybutom.
Renderowanie warunkowe treści
W nowoczesnych frameworkach (React, Vue, Svelte) często renderujesz warunkowo elementy UI:
{profile &&
null i undefined są „falsy”, więc powyższy fragment nie wyrenderuje się, jeśli profile ma którąś z tych wartości. Często jest to pożądane: null — profil nie istnieje (nie pokazujemy go); undefined — profil jeszcze się ładuje (pokazujemy loader).
Świadome modelowanie tych stanów pozwala unikać pustych sekcji i generować właściwe komunikaty dostępności (np. „Dane profilu są w trakcie ładowania”).
Formularze i komunikaty błędów
Stan pola formularza może przyjmować m.in. takie wartości:
undefined— jeszcze nie dotknięte przez użytkownika (nie wypełnione, nie odwiedzone),null— świadomie wyczyszczone lub ustawione na „brak wyboru”,''— użytkownik wpisał i usunął wartość.
Dla dostępności tylko w niektórych stanach chcesz pokazywać błędy, a w innych — neutralne podpowiedzi. Jasne rozróżnienie undefined vs null ułatwia kontrolę tego, kiedy komunikaty mają być widoczne i anonsowane przez czytniki.
Praktyczne wskazówki do codziennej pracy
-
Nie przypisuj ręcznie
undefined, jeśli nie musisz. Pozwól, byundefinedoznaczało „brak inicjalizacji” nadawany przez silnik JS. -
Używaj
null, gdy chcesz mieć jawny, „biznesowy” brak wartości. Np.currentUser: null,error: null,selectedItem: null— intencja jest czytelna. -
Do wspólnego sprawdzenia „brak wartości” używaj
value == nulllub operatora??. Traktująnulliundefinedjako „brak”, ale nie mieszają ich z pustym stringiem,0czyfalse. -
W UI filtruj dane, zanim trafią do DOM. Nie pozwalaj, by „undefined”, „null” czy
NaNpojawiały się w treści elementów lub w atrybutach dostępności. -
Świadomie modeluj stany komponentów. Np. w SPA:
undefined— dane jeszcze nie pobrane,null— dane pobrane, ale ich brak (np. nie znaleziono),- obiekt/wartość — dane dostępne.
Ćwiczenia dla ciebie
Aby utrwalić różnicę między undefined a null, wykonaj poniższe zadania:
-
Napisz funkcję
getUser(id), która:- zwraca obiekt użytkownika, jeśli go znajdzie,
- zwraca
null, jeśli użytkownik nie istnieje, - korzysta z
undefinedtylko tam, gdzie JavaScript robi to automatycznie (np. brak parametru).
-
Zaimplementuj komponent (nawet w czystym JS), który:
- pokazuje loader, gdy stan danych jest
undefined, - pokazuje komunikat „Nie znaleziono danych”, gdy stan jest
null, - pokazuje dane, gdy stanem jest obiekt.
- pokazuje loader, gdy stan danych jest
-
Dla strony z danymi z API przygotuj kontrolę jakości:
— upewnij się, że żaden tekst w DOM nie zawiera dosłownie „undefined”, „null” ani
NaN;— zadbaj, by atrybuty takie jak
alt,aria-label,titlemiały sensowne wartości zastępcze, gdy dane z API sąnulllubundefined.
W praktyce undefined i null to dwa różne narzędzia — właściwie użyte, poprawiają czytelność kodu i dostępność twojej aplikacji.





