Jak sprawdzić, czy zmienna jest tablicą w JavaScript? [duplikat]

To pytanie ma już odpowiedź tutaj:

Chciałbym sprawdzić, czy zmienna jest tablicą lub pojedynczą wartością w JavaScript.

Znalazłem możliwe rozwiązanie...

if (variable.constructor == Array)...

Czy to najlepszy sposób, aby to zrobić?

Author: Andy McCluggage, 2009-04-20

23 answers

Istnieje kilka sposobów sprawdzenia, czy zmienna jest tablicą, czy nie. Najlepszym rozwiązaniem jest to, które wybrałeś.

variable.constructor === Array

Jest to najszybsza Metoda w Chrome i najprawdopodobniej wszystkie inne przeglądarki. Wszystkie tablice są obiektami, więc sprawdzanie właściwości constructor jest szybkim procesem dla silników JavaScript.

Jeśli masz problemy z ustaleniem, czy właściwość objects jest tablicą, musisz najpierw sprawdzić, czy ta właściwość tam jest.

variable.prop && variable.prop.constructor === Array

Some other ways są:

variable instanceof Array

Ta metoda działa około 1/3 prędkości jako pierwszy przykład. Nadal dość solidne, wygląda czystsze, jeśli jesteś o ładny kod i nie tyle na wydajności. Zauważ, że sprawdzanie liczb nie działa, ponieważ variable instanceof Number zawsze zwraca false. Aktualizacja: instanceof teraz idzie 2/3 prędkości!

Array.isArray(variable)
Ten ostatni jest moim zdaniem Najbrzydszy i jeden z najwolniejszych. Działa o 1/5 prędkości jako pierwszy przykład. / Align = "left" / prototyp, jest faktycznie / align = "left" / więcej na ten temat można przeczytać tutaj https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray

Tak więc kolejna aktualizacja

Object.prototype.toString.call(variable) === '[object Array]';

Ten facet jest najwolniejszy, gdy próbuje sprawdzić tablicę. Jest to jednak punkt kompleksowej obsługi dla każdego typu, którego szukasz. Jednak, ponieważ szukasz tablicy, po prostu użyj najszybszej metody powyżej.

Również, przeprowadziłem jakiś test: http://jsperf.com/instanceof-array-vs-array-isarray/33 więc baw się trochę i sprawdź to.

Uwaga: @EscapeNetscape stworzył kolejny test jako jsperf.com leży. http://jsben.ch/#/QgYAV chciałem się upewnić, że oryginalny link pozostanie na zawsze, gdy jsperf wróci do sieci.

 1367
Author: jemiloii,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-04 11:53:18

Możesz też użyć:

if (value instanceof Array) {
  alert('value is Array!');
} else {
  alert('Not an array');
}
Wydaje mi się to dość eleganckie rozwiązanie, ale dla każdego jego własne.

Edit:

Od ES5 jest teraz także:

Array.isArray(value);

Ale to się zepsuje na starszych przeglądarkach, chyba że używasz polyfills (zasadniczo... IE8 lub podobne).

 985
Author: Brett Bender,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-04 20:41:43

Zauważyłem, że ktoś wspomniał o jQuery, ale nie wiedziałem, że jest isArray() funkcja. Okazuje się, że został dodany w wersji 1.3.

JQuery implementuje to tak jak sugeruje Peter:

isArray: function( obj ) {
    return toString.call(obj) === "[object Array]";
},

Po włożeniu dużo wiary w jQuery już (zwłaszcza ich techniki dla kompatybilności między przeglądarkami) będę albo uaktualnić do wersji 1.3 i korzystać z ich funkcji (pod warunkiem, że aktualizacja nie powoduje zbyt wiele problemów) lub użyć tej sugerowanej metody bezpośrednio w moim kod.

Wielkie dzięki za sugestie.

 73
Author: Andy McCluggage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-15 17:12:56

Istnieje wiele rozwiązań z własnymi dziwactwami. Ta strona daje dobry przegląd. Jednym z możliwych rozwiązań jest:

function isArray(o) {
  return Object.prototype.toString.call(o) === '[object Array]'; 
}
 71
Author: Peter Smit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 19:31:53

W nowoczesnych przeglądarkach (i niektórych starszych przeglądarkach), można zrobić

Array.isArray(obj)

(obsługiwane przez Chrome 5, Firefox 4.0, IE 9, Opera 10.5 i Safari 5)

Jeśli potrzebujesz obsługi starszych wersji IE, możesz użyć es5-shim do tablicy polyfill.isArray; lub dodać następujące

# 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]';
  }
};

Jeśli używasz jQuery możesz użyć jQuery.isArray(obj) lub $.isArray(obj). Jeśli używasz podkreślenia, możesz użyć _.isArray(obj)

Jeśli nie musisz wykrywać tablic utworzonych w różnych klatkach, możesz także wystarczy użyć instanceof

obj instanceof Array

Uwaga : słowo kluczowe arguments, które może być użyte do uzyskania dostępu do argumentu funkcji, nie jest tablicą, nawet jeśli (zazwyczaj) zachowuje się jak tablica:

var func = function() {
  console.log(arguments)        // [1, 2, 3]
  console.log(arguments.length) // 3
  console.log(Array.isArray(arguments)) // false !!!
  console.log(arguments.slice)  // undefined (Array.prototype methods not available)
  console.log([3,4,5].slice)    // function slice() { [native code] } 
}
func(1, 2, 3)
 54
Author: Fela Winkelmolen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-10 15:08:45

To stare pytanie, ale mając ten sam problem znalazłem bardzo eleganckie rozwiązanie, którym chcę się podzielić.

Dodanie prototypu do tablicy sprawia, że jest to bardzo proste

Array.prototype.isArray = true;

Teraz, jeśli masz obiekt, który chcesz przetestować, aby sprawdzić, czy jest tablicą, wystarczy sprawdzić nową właściwość

var box = doSomething();

if (box.isArray) {
    // do something
}

IsArray jest dostępny tylko wtedy, gdy jest tablicą

 51
Author: Ibu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-24 21:12:50

Via Crockford :

function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (value instanceof Array) {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

Główną wadą jest niemożność prawidłowego określenia tablic, które zostały utworzone w innym kontekście, np. window. Ta strona ma znacznie bardziej wyrafinowaną wersję, jeśli jest niewystarczająca.

 45
Author: Hank Gay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-20 09:07:33

Osobiście podoba mi się sugestia Piotra: https://stackoverflow.com/a/767499/414784 (dla ECMAScript 3. Dla ECMAScript 5 użyj Array.isArray())

Komentarze do posta wskazują jednak, że jeśli toString() zostanie w ogóle zmieniona, taki sposób sprawdzania tablicy zakończy się niepowodzeniem. Jeśli naprawdę chcesz być konkretny i upewnić się, że toString() nie został zmieniony i nie ma problemów z atrybutem klasy objects ([object Array] jest atrybutem klasy obiektu, który jest tablicą), to polecam zrobić coś takiego:

//see if toString returns proper class attributes of objects that are arrays
//returns -1 if it fails test
//returns true if it passes test and it's an array
//returns false if it passes test and it's not an array
function is_array(o)
{
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')
    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    }
    else
    {
        // may want to change return value to something more desirable
        return -1; 
    }
}

Zauważ, że w JavaScript the Definitive Guide 6th edition, 7.10, mówi {[1] } jest zaimplementowany przy użyciu Object.prototype.toString.call() W ECMAScript 5. Zauważ również, że jeśli masz zamiar martwić się o zmianę implementacji toString(), powinieneś również martwić się o zmianę każdej innej wbudowanej metody. Dlaczego używać push()? Ktoś może to zmienić! Takie podejście jest głupie. Powyższa kontrola jest oferowanym rozwiązaniem dla tych, którzy martwią się zmianą toString(), ale uważam, że kontrola jest niepotrzebnie.

 26
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:02:58

Kiedy pisałem to pytanie, wersja JQuery, której używałem, nie zawierała isArray funkcji. Gdyby miał, prawdopodobnie użyłbym go ufając, że implementacja jest najlepszym niezależnym od przeglądarki sposobem wykonania tego konkretnego sprawdzenia typu.

Ponieważ JQuery oferuje teraz tę funkcję, zawsze bym jej używał...

$.isArray(obj);

(od wersji 1.6.2) jest nadal zaimplementowany za pomocą porównań na łańcuchach w postaci

toString.call(obj) === "[object Array]"
 19
Author: Andy McCluggage,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-08 14:42:10

Pomyślałem, że dodam kolejną opcję dla tych, którzy mogą już używać podkreślenia.biblioteka js w swoim skrypcie. Podkreślam.js ma funkcję isArray () (zobacz http://underscorejs.org/#isArray).

_.isArray(object) 

Zwraca true, jeśli obiekt jest tablicą.

 16
Author: Benjen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-28 13:05:32

Jeśli masz do czynienia tylko z EcmaScript 5 i nowszymi, możesz użyć wbudowanej funkcji Array.isArray

Np.,

Array.isArray([])    // true
Array.isArray("foo") // false
Array.isArray({})    // false
 13
Author: JaredMcAteer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-11 14:05:20

Jeśli używasz Angular, możesz użyć angular.funkcja isArray ()

var myArray = [];
angular.isArray(myArray); // returns true

var myObj = {};
angular.isArray(myObj); //returns false

Http://docs.angularjs.org/api/ng/function/angular.isArray

 10
Author: joseph.l.hunsaker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-19 08:40:02

W JavaScript The Good Parts , istnieje funkcja sprawdzająca, czy podany argument jest tablicą:

var is_array = function (value) {
    return value &&
        typeof value === 'object' &&
        typeof value.length === 'number' &&
        typeof value.splice === 'function' &&
        !(value.propertyIsEnumerable('length'));
};

Wyjaśnia:

Najpierw pytamy, czy wartość jest prawdziwa. Robimy to, aby odrzucić wartości null i inne fałszywe. Po drugie, pytamy, czy wartość typeof to 'object'. Będzie to prawda dla obiektów, tablic i (co dziwne) null. Po trzecie, pytamy, czy wartość ma właściwość length, która jest liczbą. Zawsze będzie to prawdą dla tablic, ale zazwyczaj nie dla obiektów. Po czwarte, pytamy, czy wartość zawiera metodę splice. To znowu będzie prawdziwe dla wszystkich tablic. Na koniec pytamy, czy właściwość length jest możliwa do wyliczenia(czy length będzie produkowane przez pętlę for in?). To będzie false dla wszystkich tablic. Jest to najbardziej wiarygodny test dla macierzy, jaki znalazłem. Szkoda, że jest to tak skomplikowane.

 9
Author: Yunzhou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-03 03:44:26

Użyłem tej linijki kodu:

if (variable.push) {
   // variable is array, since AMAIK only arrays have push() method.
}
 5
Author: Saeed Neamati,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-06 08:01:24

Uniwersalne rozwiązanie znajduje się poniżej:

Object.prototype.toString.call(obj)=='[object Array]'

Począwszy od ECMAScript 5, formalnym rozwiązaniem jest:

Array.isArray(arr)

Również, dla starych bibliotek JavaScript, można znaleźć poniżej rozwiązanie, choć nie jest wystarczająco dokładne:

var is_array = function (value) {
    return value &&
    typeof value === 'object' &&
    typeof value.length === 'number' &&
    typeof value.splice === 'function' &&
    !(value.propertyIsEnumerable('length'));
};

Rozwiązania są z http://www.pixelstech.net/topic/85-How-to-check-whether-an-object-is-an-array-or-not-in-JavaScript

 4
Author: PixelsTech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-11 14:17:49

Kod, o którym mowa w https://github.com/miksago/Evan.js/blob/master/src/evan.js

  var isArray = Array.isArray || function(obj) {
    return !!(obj && obj.concat && obj.unshift && !obj.callee);};
 3
Author: didxga,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-08 15:17:29

Dla tych, którzy kod-golf, zawodny test z najmniejszą liczbą znaków:

function isArray(a) {
  return a.map;
}

Jest to powszechnie używane podczas przechodzenia / spłaszczania hierarchii:

function golf(a) {
  return a.map?[].concat.apply([],a.map(golf)):a;
}

input: [1,2,[3,4,[5],6],[7,[8,[9]]]]
output: [1, 2, 3, 4, 5, 6, 7, 8, 9]
 2
Author: Joe Frambach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-24 18:43:37

From w3schools :

function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}
 2
Author: Jahid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 13:07:14

Podobała mi się odpowiedź Briana:

function is_array(o){
    // make sure an array has a class attribute of [object Array]
    var check_class = Object.prototype.toString.call([]);
    if(check_class === '[object Array]')    {
        // test passed, now check
        return Object.prototype.toString.call(o) === '[object Array]';
    } else{
        // may want to change return value to something more desirable
        return -1; 
    }
}

Ale możesz zrobić tak:

return Object.prototype.toString.call(o) === Object.prototype.toString.call([]);
 1
Author: zeageorge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-20 17:17:31

Stworzyłem ten fragment kodu, który może zwracać prawdziwe typy.

Nie jestem jeszcze pewien wydajności, ale jest to próba poprawnego zidentyfikowania typu.

Https://github.com/valtido/better-typeOf również blogował trochę o tym tutaj http://www.jqui.net/jquery/better-typeof-than-the-javascript-native-typeof/

To działa, podobnie jak obecny typeof.

var user = [1,2,3]
typeOf(user); //[object Array]

Wydaje się, że może wymagać trochę dostrojenia, i wziąć pod uwagę rzeczy, nie natknąłem się ani nie Przetestowałem go prawidłowo. dlatego mile widziane są dalsze ulepszenia, niezależnie od tego, czy chodzi o wydajność, czy o nieprawidłowe przeportowanie typeOf.

 1
Author: Val,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-28 09:32:11

Myślę, że używając myObj.konstruktor = = obiekt i myArray.konstruktor = = Array jest najlepszym sposobem. Jest prawie 20x szybszy niż użycie ToString (). Jeśli rozszerzasz obiekty o własne konstruktory i chcesz, aby te kreacje były również uważane za "obiekty", to nie działa to, ale poza tym jest szybsze. typeof jest tak samo szybki jak metoda konstruktora, ale typeof [] = = 'object' zwraca true, co często będzie niepożądane. http://jsperf.com/constructor-vs-tostring

Jedna rzecz należy zauważyć, że null.konstruktor wyrzuci błąd, więc jeśli możesz sprawdzać wartości null, musisz najpierw zrobić if (testThing!= = null) {}

 1
Author: user1585789,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-24 20:51:27

Od ... właściwość length jest specjalna dla tablic w javascript, możesz po prostu powiedzieć

obj.length === +obj.length // true if obj is an array

Underscorejs i kilka innych bibliotek używa tej krótkiej i prostej sztuczki.

 -5
Author: TypingTurtle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-02 18:01:53

Coś, co właśnie wymyśliłem:

if (item.length) //This is an array else //not an array

 -14
Author: trololol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-12 23:01:13