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

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

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


Я рассмотрел различные решения ниже и создал тест jsperf.

2160
задан mpen 23 янв. '11 в 21:53
источник поделиться
39 ответов
  • 1
  • 2

В современных браузерах вы можете сделать

Array.isArray(obj)

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

Для обратной совместимости вы можете добавить следующие

# 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
333
ответ дан Fela Winkelmolen 06 янв. '14 в 21:11
источник поделиться

Метод, указанный в стандарте ECMAScript для поиска класса Object, заключается в использовании метода toString из Object.prototype.

if( Object.prototype.toString.call( someVar ) === '[object Array]' ) {
    alert( 'Array!' );
}

Или вы можете использовать typeof для проверки, является ли это строкой:

if( typeof someVar === 'string' ) {
    someVar = [ someVar ];
}

Или, если вас не интересует производительность, вы можете просто сделать concat для нового пустого массива.

someVar = [].concat( someVar );

Там также конструктор, который вы можете запросить напрямую:

if (somevar.constructor.name == "Array") {
    // do something
}

Ознакомьтесь с подробным описанием блога @TJ Crowder, опубликованным в его комментарии ниже.

Ознакомьтесь с этим эталоном, чтобы получить представление о том, какой метод работает лучше: http://jsben.ch/#/QgYAV

Из @Bharath конвертировать строку в массив с использованием Es6 для заданного вопроса:

const convertStringToArray = (object) => {
   return (typeof object === 'string') ? Array(object) : object 
}

предположим:

let m = 'bla'
let n = ['bla','Meow']
let y = convertStringToArray(m)
let z = convertStringToArray(n)
console.log('check y: '+JSON.stringify(y)) . // check y: ['bla']
console.log('check y: '+JSON.stringify(z)) . // check y: ['bla','Meow']
1867
ответ дан user113716 23 янв. '11 в 21:54
источник поделиться

Я бы сначала проверил, поддерживает ли ваша реализация isArray:

if (Array.isArray)
    return Array.isArray(v);

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

v instanceof Array
1225
ответ дан ChaosPandion 23 янв. '11 в 21:55
источник поделиться

jQuery также предлагает метод $.isArray():

var a = ["A", "AA", "AAA"];

if($.isArray(a)) {
  alert("a is an array!");
} else {
  alert("a is not an array!");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
284
ответ дан janr 02 апр. '12 в 15:15
источник поделиться

Это самый быстрый среди всех методов (поддерживаются все браузеры):

function isArray(obj){
    return !!obj && obj.constructor === Array;
}
84
ответ дан shinobi 06 дек. '15 в 13:12
источник поделиться

Array.isArray работает быстро, но не поддерживается всеми версиями браузеров. Таким образом, вы можете сделать исключение для других и использовать универсальный метод:

    Utils = {};    
    Utils.isArray = ('isArray' in Array) ? 
        Array.isArray : 
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }
31
ответ дан CruorVult 10 дек. '12 в 20:01
источник поделиться

Представьте, что у вас есть этот массив ниже:

var arr = [1,2,3,4,5];

Javascript (новые и старые браузеры):

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

или

function isArray(arr) {
  return arr instanceof Array;
}

или

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

затем назовите его так:

isArray(arr);

Javascript (IE9+, Ch5+, FF4+, Saf5+, Opera10. 5+)

Array.isArray(arr);

JQuery:

$.isArray(arr);

Угловой:

angular.isArray(arr);

Подчеркивание и Lodash:

_.isArray(arr);
29
ответ дан Alireza 27 дек. '17 в 16:17
источник поделиться

Простая функция для проверки:

function isArray(object)
{
    if (object.constructor === Array) return true;
    else return false;
}
20
ответ дан MidnightTortoise 04 сент. '12 в 20:56
источник поделиться

Вы можете попробовать этот подход: http://web.archive.org/web/20100424091244/http://www.ajaxdr.com/code/javascript-version-of-phps-is_array-function/

EDIT: также, если вы уже используете JQuery в своем проекте, вы можете использовать его функцию $. isArray().

16
ответ дан André Paramés 23 янв. '11 в 21:56
источник поделиться

Поскольку MDN говорит здесь:

используйте Array.isArray или Object.prototype.toString.call, чтобы различать регулярные объекты из массивов

Вот так:

  • Object.prototype.toString.call(arr) === '[object Array]', или

  • Array.isArray(arr)

13
ответ дан ajax333221 15 сент. '12 в 0:02
источник поделиться

Вы можете проверить тип переменной, является ли она массивом:

var myArray=[];

if(myArray instanceof Array)
{
....
}
12
ответ дан Ahmet DAL 15 янв. '13 в 11:58
источник поделиться

Я бы сделал функцию для проверки типа объекта, с которым вы имеете дело...

function whatAmI(me){ return Object.prototype.toString.call(me).split(/\W/)[2]; }

// tests
console.log(
  whatAmI(["aiming","@"]),
  whatAmI({living:4,breathing:4}),
  whatAmI(function(ing){ return ing+" to the global window" }),
  whatAmI("going to do with you?")
);

// output: Array Object Function String

тогда вы можете написать простую инструкцию if...

if(whatAmI(myVar) === "Array"){
    // do array stuff
} else { // could also check `if(whatAmI(myVar) === "String")` here to be sure
    // do string stuff
}
12
ответ дан Billy Moon 08 авг. '12 в 16:34
источник поделиться

Только одно линейное решение для этого вопроса

x instanceof Array

где x - это переменная, она вернет true, если x - массив, а false - если нет.

11
ответ дан Vikash Kumar 08 июня '17 в 15:48
источник поделиться

Это моя попытка улучшить этот ответ с учетом комментариев:

var isArray = myArray && myArray.constructor === Array;

Он избавляется от if/else и учитывает возможность того, что массив равен null или undefined

10
ответ дан George Jempty 01 апр. '15 в 23:35
источник поделиться

Я обновил скрипт jsperf с помощью двух альтернативных методов, а также проверки ошибок.

Оказывается, метод, определяющий постоянное значение в прототипах "Объект" и "Массив", быстрее, чем любой другой метод. Это несколько удивительный результат.

/* Initialisation */
Object.prototype.isArray = function() {
  return false;
};
Array.prototype.isArray = function() {
  return true;
};
Object.prototype._isArray = false;
Array.prototype._isArray = true;

var arr = ["1", "2"];
var noarr = "1";

/* Method 1 (function) */
if (arr.isArray()) document.write("arr is an array according to function<br/>");
if (!noarr.isArray()) document.write("noarr is not an array according to function<br/>");
/* Method 2 (value) - **** FASTEST ***** */
if (arr._isArray) document.write("arr is an array according to member value<br/>");
if (!noarr._isArray) document.write("noarr is not an array according to member value<br/>");

Эти два метода не работают, если переменная принимает значение undefined, но они работают, если вы уверены, что они имеют значение. Что касается проверки с учетом производительности, если значение представляет собой массив или одно значение, второй метод выглядит как действительный быстрый метод. Он немного быстрее, чем "экземпляр" в Chrome, в два раза быстрее, чем второй лучший метод в Internet Explorer, Opera и Safari (на моей машине).

9
ответ дан le_top 01 авг. '15 в 14:10
источник поделиться

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/isArray

Array.isArray = Array.isArray || function (vArg) {
    return Object.prototype.toString.call(vArg) === "[object Array]";
};
9
ответ дан Safareli 05 марта '13 в 11:26
источник поделиться

Я делаю это очень просто. Работает на меня. Любые недостатки?

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)
9
ответ дан rsbkk 04 апр. '15 в 9:58
источник поделиться

Я знаю, что люди ищут какой-то оригинальный javascript подход. Но если вы хотите меньше думать, посмотрите здесь: http://underscorejs.org/#isArray

_.isArray(object) 

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

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
8
ответ дан Eugene 04 апр. '12 в 3:46
источник поделиться

Вы можете использовать метод isArray, но я бы предпочел проверить

Object.getPrototypeOf(yourvariable) === Array.prototype

5
ответ дан STEEL 28 февр. '18 в 20:21
источник поделиться

В книге Стояна Стефанова есть хороший пример Шаблоны JavaScript, которые позволяют обрабатывать все возможные проблемы, а также использовать метод ECMAScript 5 Array.isArray().

Итак, вот оно:

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

Кстати, если вы используете jQuery, вы можете использовать его метод $. isArray()

5
ответ дан Salvador Dali 15 дек. '13 в 10:11
источник поделиться

Лучшее решение, которое я видел, это кросс-браузерная замена для typeof. Проверьте решение Angus Croll здесь.

Версия TL; DR приведена ниже, но статья - отличное обсуждение проблемы, поэтому вы должны ее прочитать, если у вас есть время.

Object.toType = function(obj) {
    return ({}).toString.call(obj).match(/\s([a-z|A-Z]+)/)[1].toLowerCase();
}
// ... and usage:
Object.toType([1,2,3]); //"array" (all browsers)

// or to test...
var shouldBeAnArray = [1,2,3];
if(Object.toType(shouldBeAnArray) === 'array'){/* do stuff */};
5
ответ дан John Wundes 23 марта '12 в 20:07
источник поделиться

Вот мой ленивый подход:

if (Array.prototype.array_ === undefined) {
  Array.prototype.array_ = true;
}

// ...

var test = [],
    wat = {};

console.log(test.array_ === true); // true
console.log(wat.array_ === true);  // false

Я знаю, что это святотатство "запутаться" с прототипом, но он выглядит значительно лучше, чем рекомендуемый метод toString.

Примечание. Ловушка этого подхода заключается в том, что не работает через границы iframe, но для моего это не проблема.

5
ответ дан namuol 11 янв. '13 в 11:56
источник поделиться
function isArray(value) {
    if (value) {
        if (typeof value === 'object') {
            return (Object.prototype.toString.call(value) == '[object Array]')
        }
    }
    return false;
}

var ar = ["ff","tt"]
alert(isArray(ar))
4
ответ дан RoboTamer 30 окт. '13 в 0:26
источник поделиться

Простая функция для проверки, является ли входное значение массивом следующим:

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

Это работает как кросс-браузер, так и старые браузеры. Это извлечено из T.J. Сообщение блога Броунов

4
ответ дан Brad Parks 02 февр. '14 в 3:29
источник поделиться

Самый простой и быстрый способ проверить, является ли объект массивом или нет.

 var arr = [];
  arr.constructor.name ==='Array'  //return true;

или

arr.constructor ===Array //return true;

или вы можете сделать служебную функцию:

function isArray(obj){ return obj && obj.constructor ===Array}

использование:

isArray(arr); //return true
4
ответ дан sheelpriy 01 марта '17 в 12:25
источник поделиться

Можно использовать следующее, если вы знаете, что у вашего объекта нет метода concat.

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It an array");
}
4
ответ дан yesil 24 авг. '16 в 11:02
источник поделиться

Эта функция превратит почти что-нибудь в массив:

function arr(x) {
    if(x === null || x === undefined) {
        return [];
    }
    if(Array.isArray(x)) {
        return x;
    }
    if(isString(x) || isNumber(x)) {
        return [x];
    }
    if(x[Symbol.iterator] !== undefined || x.length !== undefined) {
        return Array.from(x);
    }
    return [x];
}

function isString(x) {
    return Object.prototype.toString.call(x) === "[object String]"
}

function isNumber(x) {
    return Object.prototype.toString.call(x) === "[object Number]"
}

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

Примеры:

> arr(null);
[]
> arr(undefined)
[]
> arr(3.14)
[ 3.14 ]
> arr(1/0)
[ Infinity ]
> gen = function*() { yield 1; yield 2; yield 3; }
[Function: gen]
> arr(gen())
[ 1, 2, 3 ]
> arr([4,5,6])
[ 4, 5, 6 ]
> arr("foo")
[ 'foo' ]

N.B. строки будут преобразованы в массив с одним элементом, а не с массивом символов. Удалите проверку isString, если вы предпочтете ее наоборот.

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

4
ответ дан mpen 24 окт. '16 в 18:48
источник поделиться

Если только два типа значений, которые могут быть переданы этой функции, являются строкой или массивом строк, сохраняйте ее просто и используйте проверку typeof для возможности строки:

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}
4
ответ дан Tim Down 23 янв. '11 в 22:51
источник поделиться

К счастью, ECMA 5 представила Array.isArray() еще в декабре 2009 года. Если по какой-то причине вы используете версию JavaScript старше ECMA 5, обновите ее.

Однако, если вы настаиваете на этом, массивы имеют определенные свойства, которые отличает их от любого другого типа. Свойства, которые я не видел в других ответах. Давайте перейдем к политике JavaScript.

Массив - это объект (typeof [] === "object"), но в отличие от традиционных объектов они имеют свойство length (typeof ( {}).length === "undefined"). null также является объектом (typeof null === "object"), но вы не можете получить доступ к свойству null поскольку null не является объектом. Это ошибка в спецификации, которая полностью возвращается к самому началу JavaScript, когда объекты имеют тег типа 0 а null был представлен как буквальный нулевой указатель 0x00, что заставляло интерпретатор путать его с объектами.

К сожалению, это не учитывает [] vs {length:0}. Поэтому мы должны перейти к цепочке прототипов.

( []).__proto__ === Array.prototype && ( []).__proto__ !== Object.prototype.

Таким образом, без Array.isArray(), это примерно то самое ближайшее, что мы можем получить:

function is_array(array){
    return array !== null
        && typeof array === "object"
        && array.__proto__ === Array.prototype;
}

[ [], [1,2,3], {length: 0}, {},
  1, 0, Infinity, NaN, "1", "[1,2,3]",
  null, undefined, [null], [undefined], {a:[]},
  [{}], [{length: 0}], [Infinity], [NaN],
  {__proto__: Array.prototype}
].filter(is_array)
// Expected: [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN] ]
// Actual:   [ [], [1,2,3], [null], [undefined], [{}], [{length: 0}], [Infinity], [NaN], {__proto__: Array.prototype} ]

Объект, злонамеренно предназначенный для того, чтобы выглядеть так же, как массив, фактически проходит тест turing. Однако заменить цепочку прототипов цепочкой прототипов Array достаточно, чтобы заставить ее действовать точно так же, как массив, эффективно создавая массив. Единственная вещь в мире, которая может Array.isArray() такой объект, на самом деле не является массивом, это Array.isArray(). Но для целей, которые вы обычно проверяете, является ли объект массивом, этот объект должен хорошо сочетаться с вашим кодом. Даже поведение, когда вы изменяете длину массива искусственно, одинаково: если длина больше, чем количество элементов в массиве, у вас будут "пустые слоты" этого специального "неявного неопределенного" типа, который как-то отличается от undefined, а также === undefined; тот же тип, который является причиной того, что мы используем typeof obj !== "undefined" чтобы избежать метаданных ReferenceError поскольку obj === undefined только не выдает ошибку, если obj явно определен как undefined.

a = {__proto__: Array.prototype}; // Array {}
a.push(5)
a // [5]
a.length = 5
a // [5, empty x 4]
b = a.map(n => n*n) // [25, empty x 4]
b.push(undefined)
b.push(undefined)
b // [25, empty x 4, undefined, undefined]
b[1] // undefined
b[1] === b[5] // true
Array.isArray(a) // false
Array.isArray(b) // true

Однако не используйте is_array(). Одно дело - изобретать колесо для обучения. Это еще одна вещь, чтобы сделать это в производственном коде. Даже не используйте его как полипол. Поддержка старых версий JS означает поддержку старых браузеров, что означает поощрение использования небезопасного программного обеспечения, что позволяет подвергнуть пользователя опасности для вредоносного ПО.

3
ответ дан Braden Best 19 июля '18 в 22:12
источник поделиться
A = [1,2,3]
console.log(A.map==[].map)

В поисках кратчайшей версии вот что я получил до сих пор.

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

3
ответ дан exebook 12 марта '13 в 5:57
источник поделиться
  • 1
  • 2

Другие вопросы по меткам