Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Оператор typeof у JavaScript». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`typeof`** повертає рядок з типом переданого значення. Точно визначає всі примітивні типи, але для звичайних об'єктів, масивів і null повертає `"object"`. ```javascript typeof 42; // "number" typeof null; // "object" -- історичний баг typeof []; // "object" -- використовуй Array.isArray() ``` **Ключове:** для перевірки null використовуй `=== null`; для масивів - `Array.isArray()`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**`typeof`** повертає рядок з типом операнда. Оператор виконується під час роботи програми і може дати одне з 8 можливих значень. ## Теорія ### TL;DR - `typeof` схожий на сканер ярликів на складі: примітиви отримують унікальні теги ("number", "string"), але всі об'єкти отримують однаковий тег "object", незалежно від вмісту. - Головне обмеження: `{}`, `[]` і `null` повертають `"object"`. Різниці між ними немає. - Правило вибору: `typeof` для примітивів; `Array.isArray()`, `=== null` або `instanceof` для об'єктів. ### Швидкий приклад ```javascript typeof 42; // "number" typeof "hello"; // "string" typeof true; // "boolean" typeof undefined; // "undefined" typeof Symbol("id"); // "symbol" typeof 42n; // "bigint" typeof function(){}; // "function" typeof {}; // "object" typeof []; // "object" -- те саме, що й {} typeof null; // "object" -- баг з 1995 року, так і не виправлений typeof NaN; // "number" -- NaN залишається числовим типом ``` Три результати дивують розробників найчастіше: масиви, null і NaN. ### Ключова різниця `typeof` зчитує внутрішній тег значення, а не його структуру чи конструктор. Для кожного примітивного типу тег унікальний. Для всіх об'єктів (включно з масивами) і null тег однаковий: `"object"`. Виняток складають функції: специфікація JS дає їм окремий тег, тому `typeof function(){}` повертає `"function"`, а не `"object"`. ### Коли використовувати - Захист типу: `if (typeof x === "string")` перед викликом рядкових методів - Перевірка колбека: `typeof fn === "function"` перед викликом переданої функції - Неоголошена змінна: `typeof undeclaredVar` повертає `"undefined"` без ReferenceError - Не для об'єктів: використовуй `Array.isArray(arr)` для масивів, `value === null` для null, `instanceof` для екземплярів класів ### Як це працює всередині V8 реалізує `typeof` як одну байткод-операцію. Він зчитує тег з внутрішнього представлення значення в пам'яті: числа мають тег Smi, об'єкти вказують на HeapObject map. Перевірка займає менше наносекунди. `null` ділить тег об'єкта ще з часів Netscape 2.0 і ніколи не виправлявся, щоб не зламати існуючі сайти. ### Поширені помилки **Помилка 1:** Думати, що `typeof x === "object"` означає звичайний об'єкт. ```javascript typeof []; // "object" typeof null; // "object" // Виправлення: поєднай перевірки if (x !== null && typeof x === "object" && !Array.isArray(x)) { // тільки тепер x — справді звичайний об'єкт } ``` **Помилка 2:** Перевіряти NaN через `typeof`. ```javascript typeof NaN; // "number" -- NaN є числом за стандартом IEEE 754 // Виправлення: Number.isNaN(NaN); // true Number.isNaN("hello"); // false -- без приведення типів ``` **Помилка 3:** Очікувати, що `typeof` розрізнить масив і об'єкт. ```javascript typeof []; // "object" -- не "array" // Виправлення: Array.isArray([]); // true ``` **Помилка 4:** Звертатися до неоголошеної змінної напряму. ```javascript console.log(undeclaredVar); // ReferenceError console.log(typeof undeclaredVar); // "undefined" -- безпечно // Практичне застосування: перевірка середовища у SSR / Next.js if (typeof window !== "undefined") { // код тільки для браузера } ``` ### Де зустрічається в реальному коді - **React**: `if (typeof onClick !== "function") return null;` для захисту від відсутнього пропа - **Express.js**: `if (typeof req.body.userId !== "string") return res.status(400)` для валідації запитів - **Node.js**: `if (typeof callback === "function") fs.readFile(..., callback)` у callback-based API - **Lodash**: `_.isString(val)` всередині починається з `typeof val === "string"` Перевірка `typeof window !== "undefined"` є майже в кожному SSR-проєкті, з яким я працював. Це найпростіший спосіб відокремити браузерний код від серверного без помилок. ### Питання на співбесіді **Q:** Що повертає `typeof null` і чому? **A:** Повертає `"object"`. Це баг з 1995 року: перша реалізація JavaScript зберігала значення з числовими тегами, і null мав тег `0`, який означав "object". Виправити це неможливо без ризику зламати величезну кількість існуючого коду. **Q:** Як правильно перевірити, чи є значення масивом? **A:** Використовуй `Array.isArray(value)`. Він працює навіть між iframe-ами, на відміну від `instanceof Array`, який ламається, коли значення прийшло з іншого фрейму. **Q:** У чому різниця між `typeof` і `instanceof`? **A:** `typeof` повертає рядковий тег і працює з примітивами. `instanceof` перевіряє ланцюжок прототипів і працює лише з об'єктами. До того ж, `instanceof` ламається між iframe-ами, бо кожен фрейм має власний конструктор `Array` і `Object`. **Q:** Чому `typeof undeclaredVariable` не кидає ReferenceError? **A:** Це єдиний виняток в JavaScript, де неоголошений ідентифікатор не викликає помилки. Специфікація зробила такий виняток, щоб можна було безпечно перевіряти наявність опціональних глобалів. **Q:** Чому `typeof` такий швидкий у V8? **A:** Він зчитує один тег з внутрішнього представлення значення в пам'яті. Немає обходу прототипів, немає алокацій. Одна байткод-інструкція. ## Приклади ### Базовий: захист типу перед обробкою ```javascript function processInput(input) { if (typeof input === "number") { return input * 2; } if (typeof input === "string") { return input.toUpperCase(); } throw new Error("Unsupported type"); } processInput(5); // 10 processInput("hi"); // "HI" processInput([]); // Error: Unsupported type ``` `typeof` охороняє кожну гілку перед викликом методу. Масив потрапляє в помилку, бо `typeof [] === "object"`, а не `"array"`. ### Середній: перевірка пропсів у React-компоненті ```javascript function UserCard({ user, onClick }) { if (typeof user !== "object" || user === null) { return <div>Некоректні дані користувача</div>; } if (typeof onClick !== "function") { console.warn("onClick має бути функцією"); return null; } return <div onClick={onClick}>{user.name}</div>; } // Перевірка user === null обов'язкова: // typeof null === "object", тому без неї null пройде першу умову. ```Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.