Как проверить, является ли объект массивом? - PullRequest
2467 голосов
/ 23 января 2011

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

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


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

Ответы [ 44 ]

13 голосов
/ 08 августа 2012

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

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 голосов
/ 15 января 2013

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

var myArray=[];

if(myArray instanceof Array)
{
....
}
11 голосов
/ 04 апреля 2015

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

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)
11 голосов
/ 01 апреля 2015

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

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

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

10 голосов
/ 01 августа 2015

Я обновил 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 голосов
/ 05 марта 2013

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 голосов
/ 04 апреля 2012

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

_.isArray(object) 

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

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
5 голосов
/ 23 марта 2012

Лучшее решение, которое я видел, это кросс-браузерная замена для 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 голосов
/ 11 января 2013

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

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 голосов
/ 15 декабря 2013

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

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

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

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

...