Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Перевірка значення на масив». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Надійний спосіб перевірити масив, це `Array.isArray(value)`: він працює в усіх сучасних браузерах і Node.js та коректно розпізнає масиви навіть з інших контекстів, наприклад з iframe.** Оператор `instanceof Array` теж дає `true`, але спирається на прототип, тому ламається, коли масив створено в іншому вікні чи фреймі з власним конструктором `Array`. Універсальний, хоч і громіздкий, варіант, це `Object.prototype.toString.call(value)`, який повертає `"[object Array]"`. А `typeof` для перевірки не підходить взагалі: для масиву він завжди дає `"object"`. ```javascript Array.isArray([1, 2, 3]); // true Array.isArray('text'); // false Array.isArray({}); // false ``` **Ключове:** для перевірки на масив завжди беріть `Array.isArray(value)`, це найточніший і найкоротший спосіб.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**Щоб перевірити, що значення є масивом, використовують `Array.isArray(value)`: це сучасний і найнадійніший спосіб, що працює навіть з масивами з інших контекстів виконання.** Решта прийомів (`instanceof`, `Object.prototype.toString.call()`, `typeof`) або мають обмеження, або не розрізняють масив і звичайний об'єкт. ## Теорія ### TL;DR - `Array.isArray(value)`, це рекомендований спосіб, працює скрізь і між контекстами. - `value instanceof Array` працює, але залежить від контексту: у масиву з iframe інший `Array.prototype`. - `Object.prototype.toString.call(value)` повертає `"[object Array]"`, універсально, але громіздко. - `typeof value` для масиву завжди дає `"object"`, тому для перевірки не годиться. - Масив, це об'єкт, тому будь-яка перевірка «це об'єкт?» пропустить і `{}`, і `null`. ### Швидкий приклад ```javascript const value = [1, 2, 3]; console.log(Array.isArray(value)); // true console.log(value instanceof Array); // true console.log(Object.prototype.toString.call(value)); // "[object Array]" console.log(typeof value); // "object" ``` Три перші перевірки відповідають на питання, четверта, ні. ### Array.isArray, сучасний і надійний спосіб ```javascript Array.isArray([1, 2, 3]); // true Array.isArray('text'); // false Array.isArray({}); // false ``` Чому саме він: - Працює в усіх сучасних браузерах і в Node.js. - Правильно визначає масиви навіть з **інших контекстів**, наприклад з iframe, з Web Worker або з окремого контексту Node.js. - Не залежить від прототипу: метод перевіряє внутрішній слот значення, а не ланцюжок `__proto__`. - Це **рекомендований** спосіб перевірки. ### instanceof Array, старий, але робочий ```javascript [1, 2, 3] instanceof Array; // true 'abc' instanceof Array; // false ``` Проте є застереження: - Якщо масив створено в **іншому вікні або фреймі**, результат може бути **хибним**, бо кожен контекст має власний конструктор `Array` і власний `Array.prototype`. ```javascript // Приклад проблеми: const foreignArray = new window.frames[0].Array(1, 2, 3); console.log(foreignArray instanceof Array); // false console.log(Array.isArray(foreignArray)); // true ``` Ще одна дрібниця: `instanceof` можна обдурити через `Symbol.hasInstance` або підміну прототипу, тоді як `Array.isArray()` такій підміні не піддається. ### Перевірка через Object.prototype.toString.call() Цей спосіб універсальний для будь-яких типів, тому його часто використовують у бібліотеках. ```javascript Object.prototype.toString.call([]); // "[object Array]" Object.prototype.toString.call({}); // "[object Object]" Object.prototype.toString.call('hi'); // "[object String]" ``` Він теж не залежить від контексту виконання, але повертає рядок, який треба порівнювати вручну, тому код виходить довшим за `Array.isArray()`. ### Чому typeof не підходить ```javascript typeof []; // "object" ``` `typeof` не годиться, тому що масив, це **об'єкт**, і результат завжди буде `"object"`. Той самий рядок повернуть `{}`, `null`, `new Date()` і `new Map()`, тож жодної корисної інформації про масив ця перевірка не дає. ### Порівняння методів | Метод | Повертає для масиву | Надійність | Коментар | | --- | --- | --- | --- | | `Array.isArray(value)` | `true` | Найвища | Найкращий варіант | | `value instanceof Array` | `true` | Середня | Залежить від контексту виконання | | `Object.prototype.toString.call(value)` | `"[object Array]"` | Висока | Універсальний, але громіздкий | | `typeof value` | `"object"` | Нульова | Не розрізняє масиви та інші об'єкти | Висновок: завжди використовуйте `Array.isArray(value)`, це найточніший і найкоротший спосіб. ### Типові помилки - **Перевіряти масив через `typeof value === 'object'`.** Умова істинна також для `{}`, `null`, `Date` і `Map`. - **Забувати про `null`.** `typeof null` теж `"object"`, тому будь-яка перевірка «об'єкт» має окремо відсіювати `null`. - **Покладатися на `instanceof` у коді з iframe, Worker чи кількома контекстами.** Там на справжньому масиві ви отримаєте `false`. - **Вважати array-like масивом.** `arguments`, `NodeList` і об'єкт із полем `length` не є масивами: `Array.isArray()` поверне `false`. Щоб отримати справжній масив, використовуйте `Array.from(value)` або `[...value]`. - **Перевіряти через `value.constructor === Array`.** Властивість `constructor` легко перезаписати, до того ж на `null` і `undefined` такий код кине помилку.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.