Как вы проверяете, является ли переменная массивом в JavaScript?

Я хотел бы проверить, является ли переменная либо массивом, либо единственным значением в JavaScript.

Я нашел возможное решение...

if (variable.constructor == Array)...

Это лучший способ сделать это?

Ответы

Ответ 1

Есть несколько способов проверить, является ли переменная массивом или нет. Лучшее решение - это то, которое вы выбрали.

variable.constructor === Array

Это самый быстрый метод в Chrome и, скорее всего, во всех других браузерах. Все массивы являются объектами, поэтому проверка свойства конструктора является быстрым процессом для движков JavaScript.

Если у вас есть проблемы с выяснением, является ли свойство объекта массивом, вы должны сначала проверить, есть ли свойство там.

variable.prop && variable.prop.constructor === Array

Некоторые другие способы:

Array.isArray(variable)

Обновление 23 мая 2019 года с использованием Chrome 75, выкрикивайте @Andu Andrici за то, что я снова вернулась к нему со своим вопросом. Последний, на мой взгляд, самый уродливый и один из самых медленных из самых быстрых. Запуск около 1/5 скорости в качестве первого примера. Этот парень примерно на 2-5% медленнее, но сказать об этом довольно сложно. Твердый в использовании! Впечатлен результатом. Array.prototype, на самом деле массив. Вы можете прочитать больше об этом здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

variable instanceof Array

Этот метод работает примерно на 1/3 скорости в качестве первого примера. Все еще довольно солидно, выглядит чище, если вы все о симпатичном коде и не столько о производительности. Обратите внимание, что проверка чисел не работает, так как variable instanceof Number всегда возвращает false. Обновление: instanceof теперь идет на 2/3 скорости!

Итак, еще одно обновление

Object.prototype.toString.call(variable) === '[object Array]';

Этот парень самый медленный из-за попытки проверить массив. Тем не менее, это универсальный магазин для любого типа, который вы ищете. Однако, так как вы ищете массив, просто используйте самый быстрый метод выше.

Кроме того, я провел несколько тестов: http://jsperf.com/instanceof-array-vs-array-isarray/35 Так что повеселитесь и проверьте это.

Примечание. @EscapeNetscape создал еще один тест, поскольку jsperf.com не работает. http://jsben.ch/#/QgYAV Я хотел убедиться, что исходная ссылка останется на всякий раз, когда jsperf возвращается в онлайн.

Ответ 2

Вы также можете использовать:

if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}

Мне кажется, это довольно элегантное решение, но для каждого из них.

Изменить:

В ES5 теперь также есть:

Array.isArray(value);

Но это сломается на старых браузерах, если вы не используете полисы (в основном... IE8 или аналогичные).

Ответ 3

Я заметил, что кто-то упомянул jQuery, но я не знал, что существует функция isArray(). Оказывается, он был добавлен в версию 1.3.

jQuery реализует его, как предлагает Питер:

isArray: function( obj ) {
    return toString.call(obj) === "[object Array]";
},

Положив много веры в jQuery (особенно их методы совместимости с несколькими браузерами), я либо обновляюсь до версии 1.3, либо воспользуюсь их функцией (при условии, что обновление не вызовет слишком много проблем) или используйте этот предложенный метод непосредственно в мой код.

Большое спасибо за предложения.

Ответ 4

Существует множество решений со всеми их собственными причудами. Эта страница дает хороший обзор. Одно из возможных решений:

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

Ответ 5

В современных браузерах (и некоторых устаревших браузерах) вы можете сделать

Array.isArray(obj)

(Поддерживается Chrome 5, Firefox 4.0, IE 9, Opera 10.5 и Safari 5)

Если вам необходимо поддерживать старые версии IE, вы можете использовать ES5-подкладку к polyfill Array.isArray; или добавьте следующее

# only implement if no native implementation is available
if (typeof Array.isArray === 'undefined') {
  Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) === '[object Array]';
  }
};

Если вы используете jQuery, вы можете использовать jQuery.isArray(obj) или $.isArray(obj). Если вы используете подчеркивание, вы можете использовать _.isArray(obj)

Если вам не нужно обнаруживать массивы, созданные в разных кадрах, вы также можете просто использовать instanceof

obj instanceof Array

Примечание: ключевое слово arguments которое можно использовать для доступа к аргументу функции, не является массивом, даже если оно (как правило) ведет себя как единое целое:

var func = function() {
  console.log(arguments)        // [1, 2, 3]
  console.log(arguments.length) // 3
  console.log(Array.isArray(arguments)) // false !!!
  console.log(arguments.slice)  // undefined (Array.prototype methods not available)
  console.log([3,4,5].slice)    // function slice() { [native code] } 
}
func(1, 2, 3)

Ответ 6

Это старый вопрос, но с той же проблемой я нашел очень элегантное решение, которое хочу поделиться.

Добавление прототипа в массив делает его очень простым

Array.prototype.isArray = true;

Теперь, если у вас есть объект, который вы хотите протестировать, чтобы проверить, нужен ли ему массив, который вам нужен, чтобы проверить новое свойство

var box = doSomething();

if (box.isArray) {
    // do something
}

isArray доступен только в том случае, если его массив

Ответ 7

Через Crockford:

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

Основным недостатком упоминаний Крокфорда является невозможность правильно определить массивы, созданные в другом контексте, например, window. Эта страница имеет гораздо более сложную версию, если этого недостаточно.

Ответ 8

Мне лично нравится предложение Питера: fooobar.com/questions/990/... (для ECMAScript 3. Для ECMAScript 5 используйте Array.isArray())

Комментарии к сообщению указывают, однако, что если toString() вообще изменено, этот способ проверки массива завершится с ошибкой. Если вы действительно хотите быть конкретным и убедитесь, что toString() не был изменен, и нет никаких проблем с атрибутом класса объектов ([object Array] - это атрибут класса для объекта, который является массивом), то я рекомендую сделать что-то например:

//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it an array
//returns false if it passes test and it not an array
function is_array(o)
{
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')
    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    else
    {
        // may want to change return value to something more desirable
        return -1; 
    }
}

Обратите внимание, что в JavaScript. Окончательное руководство. 6-е издание, 7.10, говорит, что Array.isArray() реализуется с использованием Object.prototype.toString.call() в ECMAScript 5. Также обратите внимание, что если вы собираетесь беспокоиться о смене реализации toString(), вам также следует беспокойство о каждом другом встроенном методе тоже. Зачем использовать push()? Кто-то может это изменить! Такой подход глуп. Вышеупомянутая проверка является предлагаемым решением для тех, кто обеспокоен изменением toString(), но я считаю, что проверка не нужна.

Ответ 9

Когда я разместил этот вопрос, версия JQuery, которую я использовал, не включала функцию isArray. Если бы у меня было это, я бы, вероятно, просто использовал его, полагая, что реализация будет лучшим браузером, независимым способом выполнения этой конкретной проверки типа.

Так как JQuery теперь предлагает эту функцию, я всегда буду использовать ее...

$.isArray(obj);

(начиная с версии 1.6.2) Он по-прежнему реализуется с использованием сравнений строк в форме

toString.call(obj) === "[object Array]"

Ответ 10

Если вы имеете дело только с EcmaScript 5 и выше, тогда вы можете использовать встроенную функцию Array.isArray

например,

Array.isArray([])    // true
Array.isArray("foo") // false
Array.isArray({})    // false

Ответ 11

Думаю, я добавлю еще один вариант для тех, кто уже может использовать библиотеку Underscore.js в своем script. Underscore.js имеет функцию isArray() (см. http://underscorejs.org/#isArray).

_.isArray(object) 

Возвращает true, если объект является массивом.

Ответ 12

Если вы используете Angular, вы можете использовать функцию angular.isArray()

var myArray = [];
angular.isArray(myArray); // returns true

var myObj = {};
angular.isArray(myObj); //returns false

http://docs.angularjs.org/api/ng/function/angular.isArray

Ответ 13

В Crockford JavaScript Хорошие части существует функция проверки, является ли данный аргумент массивом:

var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};

Он объясняет:

Сначала мы спрашиваем, правно ли это значение. Мы делаем это, чтобы отклонить нулевые и другие значения фальши. Во-вторых, мы спрашиваем, является ли typeof значением "object". Это будет верно для объектов, массивов и (странно) null. В-третьих, мы спрашиваем, имеет ли значение свойство length, которое является числом. Это всегда будет верно для массивов, но обычно это не для объектов. В-четвертых, мы спрашиваем, содержит ли значение метод сращивания. Это снова будет верно для всех массивов. Наконец, мы спрашиваем, является ли свойство length перечислимым (длина будет создаваться с помощью цикла for for?). Это будет ложно для всех массивов. Это самый надежный тест на массивность, который я нашел. К сожалению, это так сложно.

Ответ 14

Универсальное решение ниже:

Object.prototype.toString.call(obj)=='[object Array]'

Начиная с ECMAScript 5, формальное решение:

Array.isArray(arr)

Кроме того, для старых библиотек JavaScript вы можете найти решение ниже, хотя оно недостаточно точное:

var is_array = function (value) {
    return value &&
    typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

Решения от http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript

Ответ 15

Я использовал эту строку кода:

if (variable.push) {
   // variable is array, since AMAIK only arrays have push() method.
}

Ответ 17

Для тех, кто кодирует гольф, ненадежный тест с наименьшим количеством символов:

function isArray(a) {
  return a.map;
}

Это обычно используется при перемещении/выравнивании иерархии:

function golf(a) {
  return a.map?[].concat.apply([],a.map(golf)):a;
}

input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]

Ответ 18

Из w3schools:

function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}

Ответ 19

Мне понравился ответ Брайана:

function is_array(o){
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    } else{
        // may want to change return value to something more desirable
        return -1; 
    }
}

но вы можете просто сделать следующее:

return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);

Ответ 20

Я создал этот немного кода, который может возвращать истинные типы.

Я пока не уверен в производительности, но это попытка правильно идентифицировать typeof.

https://github.com/valtido/better-typeOf также немного побеседовал об этом здесь http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/

он работает, подобно текущему типу.

var user = [1,2,3]
typeOf(user); //[object Array]

Он думает, что может потребоваться немного тонкой настройки, и принять во внимание вещи, я не сталкивался или не тестировал их должным образом. поэтому приветствуются дальнейшие улучшения, независимо от того, насколько они эффективны по производительности или неправильно переупорядочивают typeOf.

Ответ 21

Я думаю, используя myObj.constructor == Object и myArray.constructor == Массив - лучший способ. Его почти в 20 раз быстрее, чем использование toString(). Если вы расширяете объекты своими собственными конструкторами и хотите, чтобы эти творения считались "объектами", а это не работает, но в противном случае его путь быстрее. typeof так же быстро, как и метод конструктора, но typeof [] == 'object' возвращает true, что часто будет нежелательным. http://jsperf.com/constructor-vs-tostring

Следует отметить, что null.constructor выдает ошибку, поэтому, если вы можете проверить нулевые значения, вам нужно будет сначала сделать, если (testThing! == null) {}

Ответ 22

function isArray(x){
    return ((x != null) && (typeof x.push != "undefined"));
}

Ответ 23

Так как свойство .length является специальным для массивов в javascript, вы можете просто сказать

obj.length === +obj.length // true if obj is an array

Underscorejs и несколько других библиотек используют этот короткий и простой трюк.

Ответ 24

Что-то, с чем я только что придумал:

if (item.length) //This is an array else //not an array