Как правильно проверить, является ли переменная массивом в JavaScript?
Лучший способ: Array.isArray()
Начиная с ECMAScript 5.1 (ES5), в JavaScript есть встроенный метод Array.isArray(), который является единственным правильным и надёжным способом проверки, является ли значение массивом. Он работает во всех современных средах (браузеры, Node.js, Deno) и не имеет проблем с кросс-контекстной передачей данных.
const arr = [1, 2, 3];
const notArr = 'строка';
const obj = {foo: 'bar'};
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(notArr)); // false
console.log(Array.isArray(obj)); // false
console.log(Array.isArray(null)); // false
Почему не подходят другие способы?
typeof— не различает массивы и обычные объекты. Массивы наследуются отObject.prototype, поэтомуtypeof []возвращает"object". Это особенность языка, заложенная ещё в первой версии JavaScript. Для проверки массивов он бесполезен.instanceof Array— работает только в пределах одного глобального контекста (одного окна/фрейма). Если массив был создан в другом iframe или открытом окне,instanceofвернётfalse, так как у каждого окна свой конструкторArray.Array.prototype.isPrototypeOf()— имеет те же проблемы, что иinstanceof.
Как работает Array.isArray() под капотом?
Метод использует внутреннюю проверку [[Class]] значения. В современных движках это эквивалентно:
Object.prototype.toString.call(value) === '[object Array]'
Этот приём был популярен до появления Array.isArray() и до сих пор встречается в коде, но его использование не рекомендуется, так как:
- Он менее читаем;
- Может быть медленнее (хотя разница незначительна);
- Не является семантически правильным — вы используете метод объекта для проверки типа.
Полный пример с обработкой разных типов данных
function checkIfArray(value) {
if (Array.isArray(value)) {
console.log('Это массив! Длина:', value.length);
return true;
} else {
console.log('Это не массив. Тип:', typeof value);
return false;
}
}
// Тесты
checkIfArray([1, 2, 3]); // true
checkIfArray('hello'); // false
checkIfArray({length: 3}); // false (псевдомассив)
checkIfArray(new Set([1, 2])); // false
checkIfArray(null); // false
Важное замечание про псевдомассивы
Array.isArray() возвращает true только для настоящих массивов. Псевдомассивы (например, arguments, NodeList, результат document.querySelectorAll()) не являются массивами, даже если у них есть свойство length и числовые ключи. Для их преобразования в массив используйте Array.from() или spread-оператор.
Вывод
В современном JavaScript (ES5+) всегда используйте Array.isArray(). Это надёжный, быстрый и кросс-контекстно-безопасный метод. Если вы поддерживаете очень старые браузеры (IE8 и ниже), используйте полифилл на основе Object.prototype.toString, но в 2024 году такая необходимость практически отсутствует.
Альтернативный подход: проверка через constructor
Некоторые разработчики используют свойство constructor для проверки:
const arr = [1, 2, 3];
console.log(arr.constructor === Array); // true
Этот способ работает в большинстве случаев, но имеет два недостатка:
- Свойство
constructorможет быть изменено (например, черезObject.setPrototypeOf()или при наследовании); - Не работает с массивами из других контекстов (iframes), как и
instanceof.
Дополнение: как обрабатывать редкие случаи
Если вы работаете с кодом, который может получать массивы из разных окон (например, в расширениях браузера), Array.isArray() — единственный безопасный вариант. Но если вам нужно проверить, является ли объект итерируемым или похожим на массив, используйте:
function isArrayLike(value) {
return value != null && typeof value[Symbol.iterator] === 'function';
}
console.log(isArrayLike([1,2])); // true
console.log(isArrayLike('hello')); // true (строка итерируема)
console.log(isArrayLike(new Set())); // true
Помните: "массивоподобный" ≠ "массив". Если вам нужен именно массив — используйте Array.isArray(). Если вам нужно что-то, что можно перебрать в цикле — проверяйте наличие Symbol.iterator или свойство length.