Avatar ·

Как проверить, является ли объект массивом в JavaScript?

Всем привет! Я только начал изучать JavaScript и столкнулся с непонятной ситуацией. Мне нужно проверить, является ли переменная массивом, но я получаю странные результаты. Вот код: ```javascript let arr = [1, 2, 3]; let obj = {name: "John"}; let str = "hello"; console.log(typeof arr); // "object" console.log(typeof obj); // "object" console.log(typeof str); // "string" ``` Оператор `typeof` возвращает "object" как для массива, так и для обычного объекта. Из-за этого я не могу отличить массив от объекта. Пробовал проверять через `arr instanceof Array` — вроде работает, но я слышал, что этот метод может давать сбои, если массив был создан в другом фрейме или iframe. Также я видел, что некоторые используют `Array.isArray()`, но не понимаю, чем этот метод лучше или хуже других подходов. Может есть ещё какие-то способы? Мне нужно надёжное решение, которое будет работать в любых условиях — в браузере, в Node.js, и не сломается при работе с разными окнами или фреймами. Подскажите, как правильно проверять, является ли значение массивом? <<>>

Самый надёжный способ: Array.isArray()

Лучший и рекомендуемый способ проверки, является ли значение массивом в JavaScript — это использование статического метода Array.isArray(). Он возвращает true, если переданное значение является массивом, и false в противном случае.

let arr = [1, 2, 3];
let obj = {name: "John"};
let str = "hello";
let num = 42;
let func = function() {};
let nullValue = null;

console.log(Array.isArray(arr));  // true
console.log(Array.isArray(obj));  // false
console.log(Array.isArray(str));  // false
console.log(Array.isArray(num));  // false
console.log(Array.isArray(func)); // false
console.log(Array.isArray(nullValue)); // false

Почему Array.isArray() — лучший выбор?

  • Надёжность в разных контекстах: Метод корректно работает даже если массив был создан в другом фрейме, iframe, вкладке браузера или в Web Worker. Оператор instanceof может дать сбой в таких ситуациях, так как он проверяет цепочку прототипов, а разные контексты имеют разные глобальные объекты.
  • Поддержка всеми современными средами: Array.isArray() поддерживается во всех современных браузерах (IE9+), Node.js и других средах выполнения JavaScript.
  • Простота и читаемость: Код с Array.isArray() легко понять и поддерживать.

Почему другие методы могут быть ненадёжны?

1. Оператор typeof
Как вы уже заметили, typeof не отличает массив от объекта:

console.log(typeof [1,2,3]); // "object"
console.log(typeof {});      // "object"

2. Оператор instanceof
Работает, но имеет ограничения:

let arr = [1, 2, 3];
console.log(arr instanceof Array); // true

// Проблема: не работает между разными контекстами (фреймы, iframe)
let iframe = document.createElement('iframe');
document.body.appendChild(iframe);
let iframeArray = new iframe.contentWindow.Array(1, 2, 3);
console.log(iframeArray instanceof Array); // false — сбой!

3. Проверка через Object.prototype.toString()
Раньше это был популярный "хак", который до сих пор работает:

function isArray(value) {
    return Object.prototype.toString.call(value) === '[object Array]';
}

console.log(isArray([1, 2, 3])); // true
console.log(isArray({}));        // false

Этот метод надёжен, но менее читаем и медленнее, чем Array.isArray(). Именно его раньше использовали как полифилл для Array.isArray() в старых браузерах.

Полифилл для старых браузеров

Если вам нужно поддерживать очень старые браузеры (IE8 и ниже), можно использовать такой полифилл:

if (!Array.isArray) {
    Array.isArray = function(arg) {
        return Object.prototype.toString.call(arg) === '[object Array]';
    };
}

Итоговая рекомендация

Всегда используйте Array.isArray() для проверки, является ли значение массивом. Это современный, надёжный и производительный способ. Для старых браузеров добавьте полифилл сверху.

<<>>

Проверка через Object.prototype.toString.call()

Хотя Array.isArray() — это современный стандарт, метод Object.prototype.toString.call() остаётся полезной альтернативой, особенно если вы работаете в окружении, где Array.isArray может быть не определён (например, очень старые версии JavaScript-движков).

Этот метод работает следующим образом: он вызывает внутренний метод [[Class]] объекта, который возвращает строку вида [object Type]. Для массивов это всегда [object Array].

function isArray(value) {
    return Object.prototype.toString.call(value) === '[object Array]';
}

// Примеры использования
console.log(isArray([1, 2]));        // true
console.log(isArray({a: 1}));       // false
console.log(isArray("string"));     // false
console.log(isArray(null));         // false
console.log(isArray(undefined));    // false

Преимущества этого подхода

  • Надёжность: Работает корректно во всех контекстах (фреймы, iframe, разные окна), так как проверяет внутренний тип объекта, а не цепочку прототипов.
  • Универсальность: Этот метод можно использовать для проверки любых встроенных типов: [object Object], [object Date], [object RegExp] и т.д.

Недостатки

  • Меньшая производительность: Выполнение Object.prototype.toString.call() немного медленнее, чем вызов Array.isArray(), хотя в большинстве приложений эта разница незначительна.
  • Менее читаемый код: Синтаксис более громоздкий по сравнению с простым Array.isArray().

Используйте этот метод, если вам нужно поддерживать экстремально старые окружения или если вы пишете универсальную утилиту для проверки типов, которая должна работать с разными видами объектов.