it-swarm.com.ru

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

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

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


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

2344
mpen

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

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
556
Fela Winkelmolen

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

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

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

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

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

someVar = [].concat( someVar );

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

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

Проверьте тщательное лечение от @ T.J. Блог Краудера , как указано в его комментарии ниже.

Посмотрите этот benchmark , чтобы понять, какой метод работает лучше: 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']
1896
user113716

Сначала я проверю, поддерживает ли ваша реализация isArray:

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

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

v instanceof Array
1238
ChaosPandion

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>

288
janr

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

function isArray(obj){
    return !!obj && obj.constructor === Array;
}
92
shinobi

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

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);

Подчеркни и Лодаш:

_.isArray(arr);
36
Alireza

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

    Utils = {};    
    Utils.isArray = ('isArray' in Array) ? 
        Array.isArray : 
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }
32
CruorVult

Простая функция, чтобы проверить это:

function isArray(object)
{
    if (object.constructor === Array) return true;
    else return false;
}
22
MidnightTortoise

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

x instanceof Array

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

14
Vikash Kumar

Как говорит MDN здесь :

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

Как это:

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

  • Array.isArray(arr)

14
ajax333221

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

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
}
13
Billy Moon

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

var myArray=[];

if(myArray instanceof Array)
{
....
}
13
Ahmet DAL

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

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)
11
rsbkk

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

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

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

11
George Jempty

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]";
};
10
Safareli

Я обновил jsperf fiddle двумя альтернативными методами, а также проверкой ошибок.

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

/* 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/>");

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

10
le_top

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

_.isArray(object) 

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

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
9
Eugene

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

Ниже приведена версия 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

Хороший пример есть в книге Стояна Стефанова Шаблоны 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

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

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

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

var arr = [];
if (typeof arr.concat === 'function') {
    console.log("It's an array");
}

5
yesil

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

 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
5
sheelpriy

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

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

5
STEEL

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

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

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

4
Brad Parks

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

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]"
}

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

Примеры:

> 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' ]

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

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

4
mpen

Вы можете попробовать это:

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

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

obj.constructor.prototype.hasOwnProperty('Push') // false
4
VIJAY P

В вашем случае вы можете использовать concat метод Array , который может принимать как отдельные объекты, так и массив (и даже объединенный):

function myFunc(stringOrArray)
{
  var arr = [].concat(stringOrArray);

  console.log(arr);

  arr.forEach(function(item, i)
  {
    console.log(i, "=", item);
  })
}

myFunc("one string");

myFunc(["one string", "second", "third"]);

concat кажется одним из старейших методов Array (даже IE 5.5 это хорошо знает).

4
kolyaseg

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

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}
4
Tim Down
A = [1,2,3]
console.log(A.map==[].map)

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

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

4
exebook
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

К счастью, 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, что привело к тому, что интерпретатор перепутал его с объектами. 

К сожалению, это не учитывает [] против {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} ]

Объект, злонамеренно спроектированный так, чтобы выглядеть как массив, на самом деле проходит тест Тьюринга. Однако замены цепочки прототипов цепочкой прототипов Array достаточно, чтобы она действовала как массив, эффективно превращая ее в массив. Единственная вещь в мире, которая может сказать, что такой объект на самом деле не массив, это Array.isArray(). Но для целей, которые вы обычно проверяете, является ли объект массивом, указанный объект должен хорошо играть с вашим кодом. Даже поведение при искусственном изменении длины массива одинаково: если длина больше, чем количество элементов в массиве, вы будете иметь «пустые слоты» этого специального «неявного неопределенного» типа, который каким-то образом отличается от не определено, но также является === undefined; тот же тип, который является причиной, по которой мы используем typeof obj !== "undefined", чтобы избежать выброса ReferenceError, потому что obj === undefined only не выдает ошибку, если 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

Существуют и другие методы для проверки, но я предпочитаю следующий метод , Как лучше для проверки (так как вы можете легко проверять типы других объектов).

> a = [1, 2]
[ 1, 2 ]
>
> Object.prototype.toString.call(a).slice(8,).replace(/\]$/, '')
'Array'
>
> Object.prototype.toString.call([]).slice(8,-1) // best approach
'Array'

Пояснение (с простыми примерами на узле REPL) »

> o = {'ok': 1}
{ ok: 1 }
> a = [1, 2]
[ 1, 2 ]
> typeof o
'object'
> typeof a
'object'
>
> Object.prototype.toString.call(o)
'[object Object]'
> Object.prototype.toString.call(a)
'[object Array]'
>

Объект или Массив »

> Object.prototype.toString.call(o).slice(8,).replace(/\]$/, '')
'Object'
>
> Object.prototype.toString.call(a).slice(8,).replace(/\]$/, '')
'Array'
>

Нулевой или неопределенный »

> Object.prototype.toString.call(undefined).slice(8,).replace(/\]$/, '')
'Undefined'
> Object.prototype.toString.call(null).slice(8,).replace(/\]$/, '')
'Null'
>

Строка »

> Object.prototype.toString.call('ok').slice(8,).replace(/\]$/, '')
'String'

Число "

> Object.prototype.toString.call(19).slice(8,).replace(/\]$/, '')
'Number'
> Object.prototype.toString.call(19.0).slice(8,).replace(/\]$/, '')
'Number'
> Object.prototype.toString.call(19.7).slice(8,).replace(/\]$/, '')
'Number'
>

Я благодарен @mpen за предложение использовать -1 вместо регулярного выражения следующим образом.

> Object.prototype.toString.call(12).slice(8,-1)
'Number'
>
> Object.prototype.toString.call(12.0).slice(8,-1)
'Number'
>
> Object.prototype.toString.call([]).slice(8,-1)
'Array'
> Object.prototype.toString.call({}).slice(8,-1)
'Object'
>
> Object.prototype.toString.call('').slice(8,-1)
'String'
>
1
hygull
var is_array = function (value) {
   return value &&
     typeof value === 'object' &&
     typeof value.length === 'number' &&
     typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

Эта функция была взята из книги «JS the good parts», отлично подходит для меня.

1
user3367643

Вы также можете проверить с помощью свойства длины массива. Когда вы попытаетесь получить доступ к свойству длины массива, он вернет число (0 для пустого массива), а если вы попытаетесь получить доступ к свойству длины объекта, он вернет неопределенное.

if(Object.prototype.toString.call(arrayList) === '[object Array]') {
  console.log('Array!');
}
0
Partha Sarathi Nanda

Я знаю, что это старый вопрос, но теперь я нашел самый короткий ответ:

var x = [1,2,3]
console.log(x.map?1:0)
0
Luis felipe De jesus Munoz

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

function isArray (o) {
    return typeof o === "object" && o.length !== undefined;
}

isArray({}); // false
isArray(1); // false
isArray("str"); // false
isArray(function(){}); // false

isArray([]); // true

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

isArray({length:0}); // true

Если вы согласны с этим недостатком и знаете, что ваши чистые объекты не будут иметь этого свойства, это чистое решение и должно быть быстрее, чем метод Object.prototype.toString.call.

0
Sensei_Shoh

есть разница между checkout его прототипом и Array.isArray:

function isArray(obj){
    return Object.getPrototypeOf(obj) === Array.prototype
}

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

но для этого объекта Proxy:

var arr = [1,2,3]

var proxy = new Proxy(arr,{})

console.log(Array.isArray(proxy)) // true

Array.isArray примет это как массив.

0
saltfish

Лучше всего сравнить его, используя constructor, что-то вроде этого

if(some_variable.constructor === Array){
  // do something
}

Вы также можете использовать другие методы, такие как typeOf, преобразовать их в строку и затем сравнить, но сравнить с dataType всегда лучше.

0
Atishay Jain

Вы можете использовать эту функцию, чтобы получить тип данных.

var myAr  = [1,2];

checkType(myAr);

function checkType(data){
  if(typeof data ==='object'){
    if(Object.prototype.toString.call(data).indexOf('Array')!==(-1)){
      return 'array';
    } else{
      return 'object';
    }
  } else {
    return typeof data;
  }
}

if(checkType(myAr) === 'array'){console.log('yes, It is an array')};
0
Kamuran Sönecek

Поскольку мне не нравятся вызовы Object.prototype, я искал другое решение. Тем более, что решения ChaosPandion не всегда работают, а решение MidnightTortoise с isArray() не работает с массивами, поступающими из DOM (например, getElementsByTagName ). И, наконец, я нашел простое и кросс-браузерное решение, которое, вероятно, также работало бы с Netscape 4.;)

Это просто эти 4 строки (проверка любого объекта h):

function isArray(h){
    if((h.length!=undefined&&h[0]!=undefined)||(h.length===0&&h[0]===undefined)){
        return true;
    }
    else{ return false; }
}

Я уже проверил эти массивы (все возвращают true):

1) array=d.getElementsByName('some_element'); //'some_element' can be a real or unreal element
2) array=[];
3) array=[10];
4) array=new Array();
5) array=new Array();
   array.Push("whatever");

Кто-нибудь может подтвердить, что это работает для всех случаев? Или кто-нибудь находит случай, когда мое решение не работает?

0
Marcus

Вот фрагмент кода, который объяснит важный факт массивов, которые должны быть известны на ранних этапах изучения JS (в отличие от меня).

// this functions puts a string inside an array
var stringInsideArray = function(input) {
  if (typeof input === 'string') {
    return [input];
  }
  else if (Array.isArray(input)) {
    return input;
  } 
  else {
    throw new Error("Input is not a string!");
  }
}

var output = stringInsideArray('hello');
console.log('step one output: ', output); // ["hello"]

// use typeof method to verify output is an object
console.log('step two output: ', typeof output); // object

// use Array.isArray() method to verify output is an array
console.log('step three output: ', Array.isArray(output)); // true

Массивы , на самом деле, объекты.

Используя оператор typeof , вывод stringInsideArray('hello') доказывает, что ["hello"] является реально объектом. Это сбило меня с толку дольше всего, потому что я предполагал, что массивы будут типом данных JavaScript ...

Существует только 7 типов данных JS, и массивы НЕ один из них.

Чтобы ответить на ваш вопрос, использование метода Array.isArray () определяет, что output является массивом.

0
underthecode

Вы можете найти с Push как ниже:

function isArray(obj){
   return (typeof obj.Push=== 'function')?true:false;
}

var array=new Array();
or
var array=['a','b','c'];
console.log(isArray(array));

0
lalithkumar