Питання Перевірте, чи є об'єкт масивом?


Я намагаюся написати функцію, яка або приймає список рядків, або окрему рядок. Якщо це рядок, то я хочу перетворити його в масив лише на один елемент. Тоді я можу петлі над нею, не побоюючись помилки.

Отже, як перевірити, чи є змінною масив?


Нижче я зібрав різні рішення та створив a тест jsperf.


2146
2018-01-23 18:53


походження


Я думав, що ви мали на увазі "перевірити, чи є об'єкт масивом", але ви хочете перевірити, чи "об'єкт - це масив рядків або окрема рядок" конкретно. Не впевнений, чи бачите це? Чи це просто я? Я думав про щось більше схоже це... Чи є мені тут щось відсутнє? - rr1g0
TL; DR - arr.constructor === Array найшвидший - Neta
jsben.ch/#/QgYAV - орієнтир для найбільш поширених шляхів - EscapeNetscape
TL; DR - Масив.isArray (arr) починаючи з ES5; і $.isArray (arr) в jQuery. - Ondra Žižka
Просто майте на увазі, що якщо ви з будь-якої причини перезаписуєте конструктор за прототипом цього arr.constructor === Array тест повернеться помилково. Array.isArray(arr) все одно повертається справжньою, хоча. - ghaschel


Відповіді:


У сучасних браузерах ви можете зробити це

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

319
2018-01-06 18:11



Ось а більш повна список браузерів, які підтримують Array.isArray - lightswitch05
if (typeof Array.isArray === 'undefined') { можна змінити на if(!Array.isArray) { - iMatoria
За свою ціну Object.prototype.string.call(obj) може бути зловмисником, якщо об'єкт має Symbol.toStringTag на ньому. Це говорить про те, що я не знаю про будь-яке середовище, яке поставляє Symbol.toStringTag але ні Array.isArray так це здається безпечним. - Benjamin Gruenbaum


Метод, зазначений у стандарті 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. Crowder's Блог, як розміщено в його коментарі нижче.

Перевірте це орієнтир отримати уявлення про те, який метод краще виконує: http://jsben.ch/#/QgYAV

Від @ Бхарат перетворити рядок в масив, використовуючи 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']

1866
2018-01-23 18:54



+1, так, toString це один із шляхів піти. Я тут трохи підхоплююсь: blog.niftysnippets.org/2010/09/say-what.html - T.J. Crowder
Якщо ви не бажаєте вводити "[object Array]", використовуйте Object.prototype.toString.call (someVar) === Object.prototype.toString.call ([]) або створіть функцію зручності, щоб отримати тип, якщо ви не Не хочеть ввести Object.prototype.toString.call - Pramod
Ого. Метод concat - це одна хвора щура. Я б дав +2, але це не дозволено - Dark Star1
Я використовую ванільний Array.isArray, який працює в "сучасних браузерах" (тобто IE9 + і всі інші). А для підтримки старого браузера використовуйте штамп від MDN developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - David Gilbertson
Жити в сучасному світі - Array.isArray(obj) - mcfedr


Спочатку я перевірив, чи підтримує ваша реалізація isArray:

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

Ви також можете спробувати використовувати instanceof оператор

v instanceof Array

1225
2018-01-23 18:55



+1, наприклад, з масиву. Найпростіший AFAICT - Tom Auger
v instanceof Array повернеться помилково, якщо v було створено в іншому кадрі (v є екземпляром thatFrame.contentWindow.Array клас) - pepkin88
Бути конкретним: Array.isArray визначається як частина ECMAScript 5 / Javascript 1.8.5. - jevon
Дійсно просте і акуратне рішення БІЛ isArray не сумісний з деякими старими браузерами (наприклад, IE7 та IE8). Джерело: kangax.github.io/es5-compat-table/# - Wookie88
Як щодо: if (Array.isArray) повертаємо Array.isArray (v); else return v instanceof Array; - lewdev


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>


283
2018-04-02 12:15



Як довідник: api.jquery.com/jQuery.isArray - Akseli Palén
Просто зауваження, jQuery внутрішньо використовує метод toString: Джерело GitHub - Jacob Squires
@JacobSquires це залежить. Я щойно протестував тут, останній jQuery у Chrome - $.isArray === Array.isArray повертається істинно. - Renan
@Ренан: Це добре, що ви використовуєте jQuery. Він зазвичай використовує найсучасніший і найкращий спосіб зробити це, і вам не потрібно робити всю функцію, перевіряючи себе, щоб знати, що використовувати. - awe
Але ніхто не збирається використовувати JQuery JUST для цієї функції, чи не так? Я б не просто завантажив jquery, тому що я хочу перевірити, чи є щось масив: p - Automagisch


Це найшвидший серед усіх методів (підтримуються всі браузери):

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

84
2017-12-06 10:12



Ви маєте рацію, це найшвидше за тестами, які я включив у запитання. - mpen
Чи існують недоліки щодо використання цього методу? Здається набагато простіше та ефективніше, ніж прийнята, найпопулярніша відповідь. - David Meza
@shinobi - просто цікаво (і я часто це бачив) - чому ви висловлюєте умову if (obj && Array === obj.constructor) на відміну від if (obj && obj.constructor === Array) ? Чи це загублено в перекладі на англійську мову, а потім на коду? наприклад, англійські спікери, як правило, запитують "чи існує об'єкт, і чи є його конструктор з класу масивів?", тому кодування потоку при його читанні є більш логічним. чи є якісь технічні причини? - unsynchronized
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();} - unsynchronized
@ Шибоні все добре. Я вважаю, це може бути похмілля з безпечної звички c - якщо ви випадково використовувати = замість ==, він не буде компілювати як його не є призначеною змінною. - unsynchronized


Array.isArray працює швидко, але не підтримується всіма версіями браузерів. Отже, ви можете зробити виняток для інших і використовувати універсальний метод:

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

31
2017-12-10 17:01



Можливо, ви хочете додати пояснення коду, щоб його було легше зрозуміти для інших користувачів, але інакше - добре. +1 - Jeff
Вам потрібно отримати .toString() метод з Object.prototype. Наразі ви використовуєте window.toString(), що не збігається. - the system
Ти правий. window.toString робити те ж саме, що і Object.prototype.toString просто в Chrome. - CruorVult
вау ('isArray' в масиві). Ніколи не бачив це раніше. thks - Ivan Ferrer Villa
isArray не дуже швидко. Це найнижчий спосіб. - jemiloii


Уявіть, що у вас є цей масив нижче:

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

29
2017-12-27 13:17





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

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

20
2017-09-04 17:56



Я б зменшив це до однієї лінії return object.constructor === Array - але ви впевнені, що це повернеться тільки для масивів? - mpen
Може це зробити з усіма логічними виразами. Коли я бачу, водять мене гайками if(x) return true; else return false :-) Навіть якщо це зворотне, ви повинні звести вираз. - mpen
Причина, що це не повертає true для getElementsByTagName, полягає в тому, що результат цієї функції насправді є HTMLCollection, а не масивом. - Yuval A.
Це погано працює, якщо об'єкт невизначений або нульовий. - John Henckel
@ Джон Хенкель Подивись мою відповідь stackoverflow.com/a/29400289/34806 він бере до уваги як вашу турботу, так і перший коментар, все на одній лінії - George Jempty


Ви можете спробувати цей підхід: http://web.archive.org/web/3800424091244/http://www.ajaxdr.com/code/javascript-version-of-phps-is_array-function/

РЕДАГУВАТИ: також, якщо ви вже використовуєте JQuery у своєму проекті, ви можете використовувати його функцію $ .isArray ().


16
2018-01-23 18:56



Красиво знайдіть маршрут jQuery - мало хто з нас дійсно вивчає багатство своїх рідше використовуваних функцій! - Dav
+1 Добре знайдіть! Не знав, що існує jQuery isArray, це було б корисно досить давно - William Isted
У вашому підході всі об'єкти, що містять властивість push буде масив: is_array({push: true});//true - CruorVult


Як говорить MDN тут:

використовувати Array.isArray або Object.prototype.toString.call диференціювати   регулярні об'єкти з масивів

Подобається це:

  • Object.prototype.toString.call(arr) === '[object Array]', або

  • Array.isArray(arr)


13
2017-09-14 21:02