it-swarm.com.ru

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

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

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

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

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

1654
Andy McCluggage

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

variable.constructor === Array

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

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

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

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

Array.isArray(variable)

Обновите 23 мая 2019 года, используя Chrome 75, выкрикивайте @AnduAndrici за то, что я вернулась к нему со своим вопросом Последний , на мой взгляд, самый уродливый, и это один из медленный быстрый. Запуск около 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.

1554
jemiloii

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

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

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

Правка:

Что касается ES5, то теперь также есть:

Array.isArray(value);

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

1022
Brett Bender

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

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

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

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

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

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

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

76
Andy McCluggage

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

Array.isArray(obj)

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

Если вам нужно поддерживать более старые версии IE, вы можете использовать es5-shim для полифилла 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)
66
Fela Winkelmolen

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

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

Array.prototype.isArray = true;

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

var box = doSomething();

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

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

56
Ibu

Через Крокфорд :

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

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

47
Hank Gay

Мне лично нравится предложение Питера: 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 Definition Guide 6th edition, 7.10, говорится, что Array.isArray() реализован с использованием Object.prototype.toString.call() в ECMAScript 5. Также обратите внимание, что если вы будете беспокоиться об изменении реализации toString(), вам также следует беспокоиться о любых других изменениях встроенного метода. , Зачем использовать Push()? Кто-то может изменить это! Такой подход глупо. Вышеупомянутая проверка является предложенным решением для тех, кто беспокоится об изменении toString(), но я считаю, что проверка не нужна.

28
Brian

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

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

$.isArray(obj);

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

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

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

например.,

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

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

_.isArray(object) 

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

17
Benjen

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

11
joseph.l.hunsaker

В Крокфорде JavaScript The Good Parts есть функция для проверки, является ли данный аргумент массивом:

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

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

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

9
Yunzhou

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

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

5
PixelsTech

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

if (variable.Push) {
   // variable is array, since AMAIK only arrays have Push() method.
}
4
Saeed Neamati

код ссылается с 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);};
3
didxga

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

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]
2
Joe Frambach

От w3schools :

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

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

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

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

это работает, похоже на текущий typeof.

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

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

1
Val

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

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

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

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

1
user1585789