Wkurza mnie to, że nie mogę po prostu zrobić document.querySelectorAll(...).map(...)
nawet w Firefoksie 3.6, a nadal nie mogę znaleźć odpowiedzi, więc pomyślałem, że napiszę na SO pytanie z tego bloga:
http://blowery.org/2008/08/29/yay-for-queryselectorall-boo-for-staticnodelist/
Czy ktoś zna techniczny powód, dla którego nie masz tablicy? Albo dlaczego StaticNodeList nie dziedziczą tablicę w taki sposób, że można użyć map
, concat
itp?
(Przy okazji, jeśli to tylko jedna funkcja, którą chcesz, możesz zrobić coś takiego NodeList.prototype.map = Array.prototype.map;
... ale znowu, dlaczego ta funkcja jest (celowo?) Blokowana w pierwszej kolejności?)
Odpowiedzi:
Uważam, że to filozoficzna decyzja W3C. Projekt W3C DOM [specyfikacja] jest dość ortogonalny w stosunku do projektu JavaScript, ponieważ DOM ma być neutralny pod względem platformy i języka.
Decyzje takie jak „
getElementsByFoo()
zwraca uporządkowanąNodeList
” lub „querySelectorAll()
zwracaStaticNodeList
” są bardzo celowe, więc implementacje nie muszą się martwić o wyrównywanie zwracanej struktury danych na podstawie implementacji zależnych od języka (np..map
Są dostępne w tablicach w JavaScript i Ruby, ale nie na listach w C #).Niski Celem W3C: oni powiedzieć
NodeList
powinna zawierać readonly.length
właściwość typu unsigned long , ponieważ wierzą, przynajmniej wsparcie każdy może implementacja że , ale nie powie wyraźnie, że[]
operator indeks powinien być przeładowany do obsługi coraz elementy pozycyjne, ponieważ nie chcą przeszkadzać jakimś słabym, małym językowi, który się pojawia, który chce zaimplementować,getElementsByFoo()
ale nie może obsługiwać przeciążenia operatora. Jest to powszechna filozofia obecna w większości specyfikacji.John Resig wypowiedział podobną opcję jak twoja, do której dodaje :
Trochę współczuję. Gdyby DOM został napisany specjalnie z myślą o funkcjach JavaScript, byłby o wiele mniej niewygodny i bardziej intuicyjny w użyciu. Jednocześnie rozumiem decyzje projektowe W3C.
źródło
StaticNodeList
tablicę na tablicę. Poparłbym odpowiedź @ mck89 jako sposób konwersjiNodeList
/StaticNodeList
do natywnej tablicy, ale to się nie powiedzie w IE (8 obv) z błędem JScript, ponieważ te obiekty są hostowane / „specjalne”.document
,window
itp IE często wykonuje te „sposób” (na przykład jako COM obiektów), które czasami nie są zgodne z normalnego użytkowania, w małych i subtelne sposoby, takie jakArray.prototype.slice.call
bombardowanie po poddaniuStaticNodeList
;)Możesz użyć operatora rozproszenia ES2015 (ES6) :
[...document.querySelectorAll('div')]
przekonwertuje StaticNodeList na Array of items.
Oto przykład, jak go używać.
źródło
Array.from(document.querySelectorAll('div')).map(x => console.log(x.innerHTML))
Nie wiem, dlaczego zwraca listę węzłów zamiast tablicy, może dlatego, że podobnie jak getElementsByTagName zaktualizuje wynik, gdy zaktualizujesz DOM. W każdym razie bardzo prostą metodą przekształcenia wyniku w prostą tablicę jest:
a potem możesz:
źródło
slice
Jednak +1 za linię.Aby dodać do tego, co powiedział Crescent,
Nie rób tego! To wcale nie jest gwarantowane.
Żaden standard JavaScript ani DOM / BOM nie określa, że
NodeList
funkcja-konstruktora istnieje nawet jakowindow
właściwość global / lub żeNodeList
zwrócona przezquerySelectorAll
będzie dziedziczyć po niej, lub że jej prototyp jest zapisywalny, lub że funkcja taArray.prototype.map
będzie faktycznie działać na NodeList.NodeList może być „obiektem hosta” (i jest nim w IE i niektórych starszych przeglądarkach). Te
Array
metody są zdefiniowane jako dopuszczone do działania na „kod JavaScript rodzimej obiektu”, który eksponuje numeryczny ilength
właściwości, ale nie są one wymagane do pracy na obiektach gospodarza (i w IE, ale nie).Irytujące jest to, że nie dostajesz wszystkich metod tablicowych na listach DOM (wszystkie, nie tylko StaticNodeList), ale nie ma niezawodnego sposobu na obejście tego. Będziesz musiał ręcznie przekonwertować każdą listę DOM, którą wrócisz, do tablicy:
źródło
new Array(n)
po prostu daje terpowi JS wskazówkę, jak długo skończy się tablica. To mogłoby pozwolić mu na przydzielenie tej ilości miejsca z wyprzedzeniem, co potencjalnie mogłoby spowodować przyspieszenie, ponieważ można by uniknąć niektórych realokacji pamięci w miarę wzrostu tablicy. Nie wiem, czy to rzeczywiście pomaga w nowoczesnych przeglądarkach ... Podejrzewałbym, że nie jest to wymierne.Myślę, że możesz po prostu śledzić
U mnie działa idealnie
źródło
Jest to opcja, którą chciałem dodać do wachlarza innych możliwości sugerowanych przez innych tutaj. Jest przeznaczony wyłącznie do intelektualnej zabawy i nie jest zalecany .
Dla samej przyjemności , oto sposób na „zmuszenie”
querySelectorAll
do uklęknięcia i ukłonu przed Tobą:Teraz dobrze jest przejść przez tę funkcję, pokazując, kto jest szefem. Teraz nie wiem, co jest lepsze, tworząc zupełnie nową nazwaną otokę funkcji, a następnie cały kod używaj tej dziwnej nazwy (prawie w stylu jQuery) lub nadpisuj funkcję jak powyżej, aby reszta kodu nadal była w stanie aby użyć oryginalnej nazwy metody DOM
querySelectorAll
.źródło