Jaka jest najlepsza de facto standardowa metoda w różnych przeglądarkach do określenia, czy zmienna w JavaScript jest tablicą, czy nie?
Przeszukując sieć można znaleźć wiele różnych sugestii, niektóre są dobre, a niektóre są nieprawidłowe.
Na przykład poniższe podejście jest podstawowym podejściem:
function isArray(obj) {
return (obj && obj.length);
}
Zwróć jednak uwagę, co się stanie, jeśli tablica jest pusta lub obj w rzeczywistości nie jest tablicą, ale implementuje właściwość length itp.
Więc która implementacja jest najlepsza pod względem faktycznego działania, bycia na różnych przeglądarkach i nadal wydajnego działania?
javascript
arrays
stpe
źródło
źródło
Odpowiedzi:
Sprawdzanie typów obiektów w JS odbywa się za pomocą
instanceof
, npTo nie zadziała, jeśli obiekt zostanie przekazany poza granice klatki, ponieważ każda klatka ma swój własny
Array
obiekt. Możesz obejść ten problem, sprawdzając wewnętrzną właściwość [[Class]] obiektu. Aby go zdobyć, użyjObject.prototype.toString()
(to gwarantuje działanie ECMA-262):Obie metody będą działać tylko dla rzeczywistych tablic, a nie obiektów przypominających tablice, takich jak listy
arguments
obiektów lub węzłów. Ponieważ wszystkie obiekty podobne do tablic muszą miećlength
właściwość numeryczną , sprawdziłbym to następująco:Należy pamiętać, że ciągi przejdą tę kontrolę, co może prowadzić do problemów, ponieważ IE nie zezwala na dostęp do znaków ciągu według indeksu. Dlatego możesz chcieć zmienić
typeof obj !== 'undefined'
na,typeof obj === 'object'
aby wykluczyć prymitywy i obiekty hosta z typami różniącymi się od wszystkich'object'
. To nadal będzie przepuszczać obiekty tekstowe, które musiałyby zostać wykluczone ręcznie.W większości przypadków tak naprawdę chcesz wiedzieć, czy możesz iterować po obiekcie za pomocą indeksów liczbowych. Dlatego dobrym pomysłem może być sprawdzenie, czy obiekt ma
0
zamiast tego nazwaną właściwość , co można zrobić za pomocą jednego z poniższych sprawdzeń:Rzutowanie na obiekt jest niezbędne do poprawnego działania dla prymitywów przypominających tablice (tj. Łańcuchów).
Oto kod do niezawodnych kontroli tablic JS:
i iterowalne (tj. niepuste) obiekty przypominające tablice:
źródło
hasOwnProperty
metodę, więc po prostu przedrostekinstanceof
zobj.hasOwnProperty &&
; czy jest to nadal problem z IE7? moje proste testy za pośrednictwem menedżera zadań sugerują, że pamięć została odzyskana po zminimalizowaniu przeglądarki ...Pojawienie się 5. edycji ECMAScript daje nam najpewniejszą metodę testowania, jeśli zmienna jest tablicą, Array.isArray () :
Chociaż zaakceptowana odpowiedź będzie działać w ramkach i oknach w większości przeglądarek, nie w przypadku Internet Explorera 7 i starszych , ponieważ
Object.prototype.toString
wywołana tablica z innego okna zwróci[object Object]
, nie[object Array]
. Wydaje się, że IE 9 również cofnął się do tego zachowania (zobacz zaktualizowaną poprawkę poniżej).Jeśli potrzebujesz rozwiązania działającego we wszystkich przeglądarkach, możesz użyć:
Nie jest całkowicie niezniszczalny, ale zostałby złamany tylko przez kogoś, kto bardzo się stara. Działa wokół problemów w IE7 i wcześniejszych oraz IE9. Błąd nadal istnieje w IE 10 PP2 , ale może zostać naprawiony przed wydaniem.
PS, jeśli nie masz pewności co do rozwiązania, polecam przetestowanie go do treści i / lub przeczytanie wpisu na blogu. Istnieją inne potencjalne rozwiązania, jeśli nie czujesz się komfortowo przy użyciu kompilacji warunkowej.
źródło
isArray
nie zwraca true z tablic utworzonych w innych trybach dokumentów? Będę musiał się temu przyjrzeć, gdy będę miał trochę czasu, ale myślę, że najlepiej będzie zgłosić błąd w Connect, aby można go było naprawić w IE 10.Crockford ma dwie odpowiedzi na stronie 106 „Dobrej części”. Pierwsza z nich sprawdza konstruktora, ale daje fałszywe negatywy w różnych ramkach lub oknach. Oto druga:
Crockford zwraca uwagę, że ta wersja zidentyfikuje
arguments
tablicę jako tablicę, mimo że nie ma żadnej z metod tablicowych.Jego interesujące omówienie problemu zaczyna się na stronie 105.
Jest tutaj kolejna interesująca dyskusja (po Good Parts) , która obejmuje tę propozycję:
Cała dyskusja sprawia, że nigdy nie chcę wiedzieć, czy coś jest tablicą.
źródło
jQuery implementuje funkcję isArray, która sugeruje najlepszy sposób na zrobienie tego
(fragment zaczerpnięty z jQuery v1.3.2 - lekko dostosowany, aby mieć sens poza kontekstem)
źródło
Object.prototype.toString()
- jest mniej prawdopodobne, że się zepsujeKradzież od guru Johna Resiga i jQuery:
źródło
typeof
są znormalizowane?Co zamierzasz zrobić z wartością, gdy zdecydujesz, że jest to tablica?
Na przykład, jeśli zamierzasz wyliczyć zawarte wartości, jeśli wygląda to jak tablica LUB jeśli jest to obiekt używany jako tabela skrótów, to poniższy kod pobierze to, czego chcesz (ten kod zatrzymuje się, gdy funkcja zamykająca zwraca cokolwiek innego niż „niezdefiniowany”. Należy pamiętać, że NIE wykonuje iteracji po kontenerach COM ani wyliczeniach; jest to pozostawione jako ćwiczenie dla czytelnika):
(Uwaga: testy „o! = Null” zarówno dla wartości null, jak i undefined)
Przykłady użycia:
źródło
for..in
jest złe [tm])for..in
iteruje po niezliczonych właściwościach obiektów; nie powinieneś używać go z tablicami, ponieważ: (1) jest wolny; (2) nie gwarantuje zachowania porządku; (3) będzie zawierać dowolną właściwość zdefiniowaną przez użytkownika ustawioną w obiekcie lub którykolwiek z jego prototypów, ponieważ ES3 nie zawiera żadnego sposobu na ustawienie atrybutu DontEnum; mogą być inne problemy, które wypadły mi z głowyJeśli robisz to w CouchDB (SpiderMonkey), użyj
Array.isArray(array)
jak
array.constructor === Array
lubarray instanceof Array
nie działają. Używaniearray.toString() === "[object Array]"
działa, ale w porównaniu z nim wydaje się dość podejrzane.źródło
Jeśli chcesz korzystać z różnych przeglądarek, potrzebujesz jQuery.isArray .
źródło
Na w3school jest przykład, który powinien być dość standardowy.
Aby sprawdzić, czy zmienna jest tablicą, używają czegoś podobnego do tego
testowane na Chrome, Firefox, Safari, ie7
źródło
constructor
do sprawdzania typu jest zbyt kruche; zamiast tego użyj jednej z sugerowanych alternatywconstructor
to zwykła właściwość DontEnum obiektu prototypowego; może to nie stanowić problemu w przypadku typów wbudowanych, o ile nikt nie robi nic głupiego, ale w przypadku typów zdefiniowanych przez użytkownika jest to łatwe; moja rada: zawsze używajinstanceof
, co sprawdza łańcuch prototypów i nie polega na właściwościach, które można dowolnie nadpisaćJedną z najlepiej zbadanych i omawianych wersji tej funkcji można znaleźć na stronie PHPJS . Możesz utworzyć link do pakietów lub przejść bezpośrednio do funkcji . Gorąco polecam stronę za dobrze skonstruowane odpowiedniki funkcji PHP w JavaScript.
źródło
Za mało odwołań równych konstruktorom. Czasami mają różne referencje konstruktora. Dlatego używam ich reprezentacji w postaci ciągów.
źródło
{constructor:{toString:function(){ return "function Array() { [native code] }"; }}}
Wymień
Array.isArray(obj)
naobj.constructor==Array
próbki:
Array('44','55').constructor==Array
return true (IE8 / Chrome)'55'.constructor==Array
return false (IE8 / Chrome)źródło