Как проверить, является ли переменная массивом в JavaScript? [дубликат]

этот вопрос уже есть ответ здесь:

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

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

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

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

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

23 ответов


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

variable.constructor === Array

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

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

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

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

variable instanceof Array

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

Array.isArray(variable)

этот последний, на мой взгляд, самый уродливый, и это один из самый медленный. Запуск около 1/5 скорости в качестве первого примера. Матрица.прототип, на самом деле массив. подробнее об этом можно прочитать здесь https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

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

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

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

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

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


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

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

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

Edit:

по состоянию на ES5 теперь также:

Array.isArray(value);

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


Я заметил, что кто-то упомянул jQuery, но я не знал, что есть isArray()


есть несколько решений со всеми своими причудами. на этой странице дает хороший обзор. Одним из возможных решений является:

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

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

Array.isArray(obj)

(при поддержке Chrome 5, Firefox 4.0, IE 9, Opera 10.5 и Safari 5)

Если вам нужно поддерживать более старые версии IE, вы можете использовать в ES5-shim и к массиву polyfill.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

Примечание: the 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)

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

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

Array.prototype.isArray = true;

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

var box = doSomething();

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

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


Via Крокфорд:

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

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


мне лично нравится предложение Петра:https://stackoverflow.com/a/767499/414784 (для 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's an array
//returns false if it passes test and it's 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 The Definitive Guide 6th edition, 7.10, говорится Array.isArray() реализуется с помощью Object.prototype.toString.call() в ECMAScript 5. Также обратите внимание, что если вы собираетесь беспокоиться о toString()реализация меняется, вы также должны беспокоиться о каждом другом встроенном изменении метода. Зачем использовать push()? Кто-то может это изменить! Такой подход глуп. Вышеуказанная проверка является предлагаемым решением для тех, кто беспокоится о toString() меняется, но я считаю, что чек не нужен.


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


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

_.isArray(object) 

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


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

например,

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

Если вы используете 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


в Крокфорд это JavaScript Хорошие Части, есть функция для проверки, является ли данный аргумент массивом:

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

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

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


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

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

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

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


код ссылка https://github.com/miksago/Evan.js/blob/master/src/evan.js

  var isArray = Array.isArray || function(obj) {
    return !!(obj && obj.concat && obj.unshift && !obj.callee);};

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

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]

С w3schools:

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

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

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([]);

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

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

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

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

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

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


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

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


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

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

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


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

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