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

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

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


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

2289
задан 23 янв. '11 в 21:53
источник поделиться
42 ответов
  • 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
480
ответ дан 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']
1882
ответ дан 23 янв. '11 в 21:54
источник

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

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

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

v instanceof Array
1233
ответ дан 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
ответ дан 02 апр. '12 в 15:15
источник

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

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

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

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);
35
ответ дан 27 дек. '17 в 16:17
источник

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

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

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

function isArray(object)
{
    if (object.constructor === Array) return true;
    else return false;
}
20
ответ дан 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
ответ дан 23 янв. '11 в 21:56
источник

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

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

Вот так:

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

  • Array.isArray(arr)

13
ответ дан 15 сент. '12 в 0:02
источник

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

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
ответ дан 08 авг. '12 в 16:34
источник

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

var myArray=[];

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

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

x instanceof Array

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

12
ответ дан 08 июня '17 в 15:48
источник

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

Array.prototype.isArray = true;

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

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

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

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

10
ответ дан 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
ответ дан 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
ответ дан 05 марта '13 в 11:26
источник

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

_.isArray(object) 

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

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

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

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
ответ дан 11 янв. '13 в 11:56
источник

В книге Стояна Стефанова есть хороший пример Шаблоны 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
ответ дан 15 дек. '13 в 10:11
источник

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

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

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

Лучшее решение, которое я видел, это кросс-браузерная замена для 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
ответ дан 23 марта '12 в 20:07
источник
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
ответ дан 30 окт. '13 в 0:26
источник

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

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
ответ дан 24 окт. '16 в 18:48
источник

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

 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
ответ дан 01 марта '17 в 12:25
источник

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

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

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

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

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

4
ответ дан 02 февр. '14 в 3:29
источник

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

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}
4
ответ дан 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
ответ дан 19 июля '18 в 22:12
источник

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

var arr = []; (or) arr = new Array();
var obj = {}; (or) arr = new Object();

arr.constructor.prototype.hasOwnProperty('push') //true

obj.constructor.prototype.hasOwnProperty('push') // false
3
ответ дан 25 февр. '16 в 8:52
источник
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос