Чому typeof null дорівнює object
typeof null повертає "object", і це історична помилка JavaScript, а не логічна властивість мови. Вона живе в мові з 1995 року і залишена навмисно, щоб не зламати мільйони старих скриптів.
Теорія
TL;DR
typeof null === "object", результат саме такий і змінювати його ніхто не буде.- Причина в ранньому 32-бітному представленні значень, де тег об'єкта був
000, аnullскладався з самих нулів. - Це офіційно визнана «відома помилка», задокументована в ECMAScript.
- Не виправили через зворотну сумісність: правки поламали б величезну кількість робочого коду.
- Для перевірки на
nullвикористовуйтеvalue === null, а неtypeof. - Щоб відрізнити справжній об'єкт від
null, потрібна складена умова.
Швидкий приклад
typeof null === "object"; // trueРезультат: "object".
Історична причина
У ранніх версіях JS значення зберігалися у вигляді 32-бітних тегованих даних:
- перші 3 біти вказували на тип даних;
- решта 29 біт зберігали саме значення.
Для об'єктів використовувався типовий тег 000, тобто три нулі на початку 32-бітного значення. А в null усе значення складалося з нулів (0x00).
Тому під час перевірки typeof null рушій бачив перші три біти 000 і робив висновок, що це об'єкт. Так і з'явилося:
typeof null; // "object"Чому це не виправили
Тому що мільйони старих скриптів по всьому інтернету можуть залежати від цієї поведінки. Виправлення призвело б до масових поломок.
Тому специфікація ECMAScript залишила це як «відому помилку», але офіційно задокументувала її.
Як правильно перевіряти null
Через цей баг не можна використовувати лише typeof для перевірки на null.
Неправильно:
if (typeof value === 'object') {
// тут value цілком може бути null!
}Правильно:
if (value === null) {
console.log('This is null');
}Або якщо треба відрізнити null від інших об'єктів:
if (typeof value === 'object' && value !== null) {
console.log('This is an object, but not null');
}Приклад для наочності
console.log(typeof null); // "object"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(null === {}); // false
console.log(null === undefined); // falseУсі три (
null,{},[]) повертають"object", але це різні типи даних.
Підсумкова таблиця
| Перевірка | Результат | Пояснення |
|---|---|---|
typeof null | "object" | Історична помилка реалізації |
null === null | true | Саме значення дорівнює собі |
typeof undefined | "undefined" | Очікувана поведінка |
typeof {} | "object" | Справжній об'єкт |
typeof [] | "object" | Масив це підтип об'єкта |
Типові помилки
- Перевіряти об'єкт через
typeof value === 'object'без додаткової умови.nullпройде таку перевірку, і наступне звертання до властивості кинеTypeError. - Вважати, що
nullце об'єкт.nullце окремий примітивний тип;"object"віддає лише операторtypeof. - Плутати
nullіundefined.null === undefinedдаєfalse, хочаnull == undefinedдаєtrueчерез приведення типів. - Сподіватися, що баг колись виправлять. Він зафіксований у специфікації назавжди, пишіть код з розрахунку на нього.
- Використовувати
typeof value === 'null'. Такого рядкаtypeofне повертає ніколи, умова завжди буде хибною.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.