Skip to main content

Різниця між null та undefined

null та undefined - обидва позначають "немає значення" в JavaScript, але перший з'являється автоматично, а другий твій код встановлює явно.

Теорія

TL;DR

  • undefined JavaScript-рушій встановлює сам, коли змінна оголошена але не отримала значення
  • null це значення яке ти пишеш явно, щоб сказати "тут навмисно нічого"
  • Аналогія: undefined — порожня поштова скринька (місце є, листа немає); null — записка всередині: "навмисно порожньо"
  • Обидва є falsy, тому if (!value) спіймає обидва. Щоб розрізнити, використовуй суворе порівняння (===)
  • Правило: нехай undefined сигналізує про неініціалізований стан; null виставляй коли навмисно очищуєш значення

Швидкий приклад

javascript
let uninitialized; // undefined за замовчуванням console.log(uninitialized); // undefined let cleared = "hello"; cleared = null; // явне скидання console.log(cleared); // null console.log(typeof uninitialized); // "undefined" console.log(typeof cleared); // "object" (спадковий баг з 1995-го)

typeof null повертає "object", а не "null". Це відомий баг JavaScript з 1995 року, який залишили щоб не зламати існуючий код.

Ключова різниця

undefined з'являється без твоїх дій. Оголоси змінну без присвоєння, зверни до відсутньої властивості об'єкта, виклич функцію без return — рушій підставить undefined. null твій код має встановити явно. Це сигнал: поле існує і воно навмисно порожнє. Різниця важлива в API та моделях даних, де "не існує" і "навмисно відсутнє" не одне й те саме.

Коли використовувати

  • Змінна оголошена але ще не присвоєна: залиш як є, рушій подбає сам
  • Властивість об'єкта яку хочеш очистити: встанови null
  • JSON-відповідь API для відсутнього поля: використовуй null (undefined повністю випадає з JSON.stringify)
  • Функція без явного return: повертає undefined за замовчуванням
  • Дані сесії після виходу з системи: req.user = null — свідоме очищення, не пропущена ініціалізація

Порівняльна таблиця

Аспектundefinednull
ПоходженняАвтоматично (рушій)Явно (твоє присвоєння)
typeof"undefined""object"
Нестроге порівняння ==Рівне nullРівне undefined
Строге порівняння ===Рівне лише собіРівне лише собі
JSON.stringifyВластивість повністю випадаєСеріалізується як "null"
Типове використанняВідсутні властивості, неініціалізовані змінніНавмисно порожні поля, API-відповіді

Як рушій це обробляє

Під час фази створення контексту виконання (execution context) V8 присвоює undefined кожній оголошеній змінній до запуску будь-якого коду. Саме тому читання var до рядка її присвоєння дає undefined замість помилки. null зберігається внутрішньо як тегований вказівник на порожній слот, через що typeof null повертає "object" замість "null".

Типові помилки

Перевірка через == коли потрібна точність

javascript
let val = null; if (val == null) console.log('знайшли'); // true, але спіймає і undefined

null == undefined дає true. Якщо потрібно спіймати лише null, використовуй val === null. Якщо обидва прийнятні, val == null підійде — але пам'ятай що він спіймає і те, і інше.

Очікування що typeof null поверне "null"

javascript
if (typeof foo === 'null') {} // ніколи не виконається

Для перевірки null завжди використовуй строге порівняння: foo === null.

undefined тихо зникає з JSON

javascript
JSON.stringify({ a: undefined, b: null }); // Результат: '{"b":null}'

Це класична пастка для бекенд-команд. Ендпоінт повертає { field: undefined } вважаючи що поле є, але клієнт отримує {}. Якщо поле має з'являтись у відповіді навіть порожнім, використовуй null.

Нестроге порівняння приховує реальний стан

javascript
const data = { user: { profile: null } }; if (data.user.profile == undefined) { console.log('safe'); // спрацьовує, бо null == undefined }

Умова виконується і маскує факт що profile явно встановлено в null. Для точності використовуй === undefined.

Де зустрічається у реальному коді

  • React: useState(null) як початковий стан до завантаження даних
  • Express: req.user = null після виходу — явне очищення сесії
  • Redux: state.error = null для скидання помилки між запитами (зберігання undefined спричиняє застарілі повідомлення які не очищаються між dispatch-ами)
  • Node.js fs.readFile: параметр err у callback дорівнює null при успіху, не undefined
  • Lodash: _.isNil(value) перевіряє null || undefined коли обидва прийнятні

Питання на співбесіді

Q: Що повертає typeof null і чому?
A: Повертає "object". В оригінальній C-реалізації JavaScript null мав той самий тег типу що й об'єкти (0x00). Баг не виправили щоб не зламати існуючий код.

Q: Як null та undefined поводяться в умовних виразах?
A: Обидва є falsy, тому if (!value) спіймає обидва. Для розрізнення використовуй строге порівняння: value === null або value === undefined.

Q: Що відбувається з undefined в JSON?
A: JSON.stringify повністю прибирає властивості зі значенням undefined. null серіалізується як "null". Тому API використовують null для відсутніх даних.

Q: Що таке void 0 і навіщо деякі мініфайкери його використовують?
A: void 0 завжди обчислюється як undefined. У старому JavaScript без strict mode глобальний undefined можна було перезаписати. void 0 — безпечна альтернатива. В сучасному коді зі strict mode це не потрібно.

Q: Як відрізнити відсутній ключ від ключа зі значенням undefined?
A: Обидва повертають undefined при зверненні. Але 'key' in obj дає false для відсутнього ключа і true для ключа явно встановленого в undefined. Ось як їх розрізнити.

Приклади

Базовий: автоматичне проти явного присвоєння

javascript
// undefined: рушій встановлює сам, без твоїх дій let username; console.log(username); // undefined function greet(name) { console.log(name); } greet(); // undefined - аргумент не передано // null: ти встановлюєш навмисно let currentUser = null; // ще не авторизований console.log(currentUser); // null

undefined з'являється коли щось відсутнє або не присвоєне. null є в коді лише тоді коли ти його туди поклав.

Реальний сценарій: Express-обробник та JSON-відповідь

javascript
app.get('/user/:id', (req, res) => { const user = db.getUser(req.params.id); if (user === undefined) { // db.getUser нічого не знайшла — не те саме що "користувач без ролі" return res.status(404).json({ error: 'User not found' }); } // Явно очищуємо чутливе поле перед відправкою res.json({ ...user, passwordHash: null }); }); // GET /user/123 (є): { id: 123, name: "Alice", passwordHash: null } // GET /user/999 (нема): 404, { error: "User not found" }

db.getUser повертає undefined коли запис не знайдено. Відповідь встановлює passwordHash в null, щоб поле залишилось у JSON-відповіді але не містило чутливих даних.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?