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

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

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

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

 Neta23 нояб. 2015 г., 23:37
TL; DR - arr.constructor === Array самый быстрый
 ghaschel23 февр. 2018 г., 18:44
Просто имейте в виду, что если вы по какой-либо причине перезапишите свой конструктор с помощью прототипа,arr.constructor === Array тест вернет false.Array.isArray(arr) все еще возвращает истину, хотя.
 rr1g023 июл. 2015 г., 20:23
Я думал, что вы хотели «проверить, является ли объект массивом», но вы хотите проверить, является ли «объект массивом строк или отдельной строкой». Не уверены, что видите это? Или это только у меня так? Я думал о чем-то более похожемэто... я здесь что-то упустил?
 Ondra Žižka19 дек. 2016 г., 10:55
TL; DR - Массив.IsArray (обр) начиная с ES5; и $.IsArray (обр) в jQuery.
 EscapeNetscape24 окт. 2016 г., 19:34
jsben.ch/#/QgYAV - эталон для самых распространенных способов

Ответы на вопрос(30)

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

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 хорошо это знает).

здесь:

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

Нравится:

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

Array.isArray(arr)

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

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

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

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

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

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

function isArray(object)
{
    if (object.constructor === Array) return true;
    else return false;
}
 mpen04 сент. 2012 г., 20:52
Может сделать это со всеми логическими выражениями. Сводит меня с ума, когда я вижуif(x) return true; else return false :-) Даже если это задом наперед, вы должны отрицать выражение.
 John Henckel20 мар. 2015 г., 16:58
Это плохо работает, если объект не определен или имеет значение null.
 Yuval A.04 дек. 2014 г., 18:35
Причина, по которой это не возвращает true для getElementsByTagName, заключается в том, что результатом этой функции является на самом деле HTMLCollection, а не массив.
 mpen04 сент. 2012 г., 20:39
Я бы сократил это до одной строкиreturn object.constructor === Array - но вы уверены, что это вернет истину только для массивов?
 George Jempty01 апр. 2015 г., 22:37
@JohnHenckel Посмотри мой ответstackoverflow.com/a/29400289/34806 он учитывает как вашу озабоченность, так и самый первый комментарий, все в одной строке

которое я видел, это кросс-браузерная замена для 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 */};

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

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 границы, но для моего случая использования это не проблема.

 test3021 июл. 2014 г., 11:40
это не лучше с точки зрения производительности, по крайней мере, на FF30 на Ubuntu 64-bit
 datico10 окт. 2013 г., 02:32
Работает ли на IE8 32 бит и 64 бит.
 namuol08 авг. 2015 г., 01:56
@ Берги: Да, это должно быть очевидно. Если вы устанавливаетеobj.array_ = trueтогда тытолько обманывают себя.
 Bergi07 авг. 2015 г., 09:18
одураченныйwat = {array_: true} объекты.
 Bergi08 авг. 2015 г., 18:15
@namuol: я не обязательно обманываю себя. Достаточно часто объекты используются в качестве словарей. Думать оcache объект для запоминания результатов поиска, который использует строки поиска в качестве ключей свойств. Что делать, если пользователь ищетarray_? Ваш объект становится массивом из-за этого? Это просто ошибка.
Решение Вопроса

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

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
 NobleUplift20 авг. 2018 г., 23:45
Почемуinstanceof Array сбой, если массив из другого фрейма?
 lightswitch0517 дек. 2014 г., 19:51
Вотболее полный список браузеров, которые поддерживаютArray.isArray
 iMatoria21 мая 2018 г., 06:38
if (typeof Array.isArray === 'undefined') { может быть изменен наif(!Array.isArray) {
 jschoi22 сент. 2018 г., 09:45
@NobleUplift:instanceof Array не удается, если массив из другого кадра, потому что каждый массив из этого другого кадра имеет разныеArray конструктор и прототип. По соображениям совместимости / безопасности каждый кадр имеет свою собственную глобальную среду, включая глобальные объекты.Object глобальный от одного кадра отличается отObject глобальный от другого. Так же дляArray Глобал.Аксель Раушмайер больше об этом говорит.
 Benjamin Gruenbaum06 июл. 2018 г., 12:27
Для чего это стоитObject.prototype.string.call(obj) может быть подделан, если объект имеетSymbol.toStringTag в теме. Тем не менее, я не знаю ни о какой среде, которая отправляетSymbol.toStringTag но нетArray.isArray так что это кажется безопасным.

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

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 здесь, потому что этосамый надежный а также самый простой.

указанный в стандарте 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
}

Проверьтетщательное лечение из@ T.J. 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']
 David Gilbertson11 окт. 2013 г., 06:40
Я использую ванильный Array.isArray, который работает в «современных браузерах» (то есть IE9 + и всех остальных). А для поддержки старых браузеров используйте шайбу от MDNdeveloper.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
 Pramod15 мар. 2013 г., 07:15
Если вы не хотите вводить «[object Array]», используйте Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) или создайте вспомогательную функцию для получения типа, если вы не не хочу набирать Object.prototype.toString.call
 T.J. Crowder23 янв. 2011 г., 19:57
+1 Да,toString это один из способов пойти. Я делаю небольшую сводку здесь:blog.niftysnippets.org/2010/09/say-what.html
 mcfedr13 нояб. 2015 г., 00:53
Жить в современном мире -Array.isArray(obj)
 Ben14 авг. 2012 г., 18:11
typeof new String('beans') > 'объект'

если вы знаете, что у вашего объекта нет метода concat.

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

 Alireza09 апр. 2017 г., 15:23
Это хороший трюк, но его можно переопределить ... но в большинстве случаев следует получить результат

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 (на моей машине).

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

x instanceof Array

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

 ChristoKiwi16 июн. 2017 г., 03:38
Гораздо чище и в будущем безопасно! Это илиtypeof сравнение.
 abalter27 апр. 2018 г., 07:24
К сожалению, это на самом деле бесполезно без try / catch, потому что если "x"объект такие как{} массив, то вы получите синтаксическую ошибку.
 Dan Zuzevich20 авг. 2017 г., 14:11
Это то, что получает хорошую поддержку браузера? Мне это нравится.

$.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>

 Automagisch17 февр. 2017 г., 14:46
Но никто не собирается использовать jQuery ПРОСТО ДЛЯ ЭТОЙ функциональности, верно? Я не просто скачал бы jquery, потому что я хочу проверить, является ли что-то массивом: p
 Jacob Squires17 апр. 2014 г., 03:25
Просто обратите внимание, jQuery использует метод toString для внутреннего использования:GitHub Source
 awe02 дек. 2015 г., 10:55
@Renan: Это хорошая вещь об использовании jQuery. Обычно для этого используется самый современный и лучший метод, и вам не нужно выполнять все функции, проверяя себя, чтобы знать, что использовать.
 Renan22 окт. 2014 г., 16:12
@JacobSquires это зависит. Я только что проверил здесь, последний JQuery на Chrome -$.isArray === Array.isArray возвращается правда.
 Akseli Palén09 мая 2012 г., 00:46
Как ссылка:api.jquery.com/jQuery.isArray

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

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

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

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

 Marco Demaio18 февр. 2014 г., 15:49
+1: почему не простоif(!Array.isArray) {... ?

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

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

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

obj.constructor.prototype.hasOwnProperty('push') // false
 Alireza09 апр. 2017 г., 15:26
Есть много простых способов сделать это!

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

function someFunc(arg) {
    var arr = (typeof arg == "string") ? [arg] : arg;
}
 mpen23 янв. 2011 г., 21:01
Да ... это сработало бы для этого сценария, но не в целом. Все равно закончилось использованием varargs. :)
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))

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

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

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

 TechTurtle21 февр. 2017 г., 18:37
конструктор недоступен в ES5
 George Jempty21 февр. 2017 г., 18:49
@TechTurtle Вы уверены? Этот код работает вES6
A = [1,2,3]
console.log(A.map==[].map)

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

 WiredPrairie27 окт. 2013 г., 21:48
К вашему сведению: это не работает через iFrames (stackoverflow.com/questions/460256/...)
 dmi3y31 мар. 2013 г., 04:47
небольшое происхождение моегоA.map !== undefined но да, это может быть скользкой дорогой в мире мартышек;)

является ли объект массивом или нет.

 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

тки?

Array.prototype.isArray = true;

a=[]; b={};
a.isArray  // true
b.isArray  // (undefined -> false)
 Bergi07 авг. 2015 г., 09:17
одураченный{isArray:true}
 Roy Tinker19 дек. 2016 г., 21:52
JSON.parse(someDataFromElsewhere).items.isArray может вернуть true (в зависимости от данных) и нарушить ваш код.

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

    Utils = {};    
    Utils.isArray = ('isArray' in Array) ? 
        Array.isArray : 
        function (value) {
            return Object.prototype.toString.call(value) === '[object Array]';
        }
 jemiloii12 дек. 2014 г., 17:01
isArray совсем не быстр. Это самый медленный метод.
 the system15 февр. 2013 г., 19:00
Вам нужно получить.toString() метод изObject.prototype, Прямо сейчас вы используетеwindow.toString(), что не то же самое.
 CruorVult18 февр. 2013 г., 12:17
Ты прав.window.toString сделать так же, какObject.prototype.toString только в хроме.
 David Winiecki13 дек. 2014 г., 04:42
Почему бы просто не добавить его в Array, а не в Utils? (Я знаю, что вам не нужны дополнительные свойства для новых объектов массива, но я думаю, что это произойдет, только если вы добавите isArray в Array.prototype.)

с которым вы имеете дело ...

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
}

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

 mpen28 февр. 2018 г., 18:36
Почему вы предпочитаете это?
 mpen02 мар. 2018 г., 00:11
Легко помешатьpastebin.com/MP8d5bCE Кроме того, у вас есть тесты производительности, чтобы подтвердить ваши "самые быстрые" претензии?
 STEEL01 мар. 2018 г., 11:32
@mpenObject.getPrototypeOf(yourvariable) он возвращает прототип объекта Array. И код является самым быстрым и безопасным, чтобы на него можно было положиться.

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

    return Object.prototype.toString.call(vArg) === "[object Array]";
};

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

_.isArray(object) 

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

(function(){ return _.isArray(arguments); })();
=> false
_.isArray([1,2,3]);
=> true
 Michał Perłakowski09 янв. 2016 г., 22:53
«Если не включен еще один тег для фреймворка / библиотеки, ожидается чистый ответ JavaScript».

поддерживает ли ваша реализацияisArray:

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

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

v instanceof Array
 Wookie8801 июл. 2013 г., 12:16
Действительно простое и аккуратное решение, НО isArray не совместим с некоторыми старыми браузерами (например, IE7 и IE8). Источник:kangax.github.io/es5-compat-table/#
 pepkin8803 янв. 2012 г., 03:08
v instanceof Array вернет ложь, еслиv был создан в другом кадре (v это примерthatFrame.contentWindow.Array класс).
 jevon23 окт. 2012 г., 07:38
Чтобы быть конкретным:Array.isArray определяется как часть ECMAScript 5 / Javascript 1.8.5.
 lewdev10 янв. 2015 г., 00:05
Как насчет: if (Array.isArray) вернуть Array.isArray (v); иначе вернуть v instanceof Array;
 Stijn de Witt12 июл. 2015 г., 16:29
или просто:return (Array.isArray && Array.isArray(v)) || (v instanceof Array);

var myArray=[];

if(myArray instanceof Array)
{
....
}
 mpen15 янв. 2013 г., 17:30
Несколько человек уже упоминалиinstanceof.. Я думаю, что это терпит неудачу в нескольких странных сценариях.

function isArray(obj){
    return !!obj && obj.constructor === Array;
}
 unsynchronized26 июн. 2016 г., 08:35
@shinobi все хорошо. я предполагаю, что это может быть похмелье от безопасной привычки c - если вы случайно используете = вместо ==, он не будет компилироваться, поскольку не является присваиваемой переменной
 unsynchronized26 июн. 2016 г., 03:54
@shinobi - просто любопытно (и я часто видел это) - почему вы формулируете условиеif (obj && Array === obj.constructor) в отличие отif (obj && obj.constructor === Array) ? Это потерянное в переводе на английский, а затем на код? Например, говорящие на английском языке обычно задают вопрос «существует ли объект и является ли он конструктором из класса массива?», поэтому поток кода при чтении более логичен. или есть какая-то техническая причина?
 mpen06 дек. 2015 г., 22:59
Вы правы, это самый быстрый результат по тестам, которые я включил в вопрос.
 David Meza26 янв. 2016 г., 19:35
Есть ли недостатки у этого метода? Это кажется намного более простым и эффективным, чем принятый, лучший ответ.
 unsynchronized26 июн. 2016 г., 08:10
function object_type(o){var t = typeof(o);return ((t==="object") && (o.constructor===Array)) ? "array" : t;} /*allows you to */ switch(object_type(o)){ case 'array': break; case 'object' : o.dosomething();}

Ваш ответ на вопрос