Użyłem JSLint na moim pliku JavaScript. Zgłoszył błąd:
for( ind in evtListeners ) {
Problem w linii 41 znak 9: Ciało for in powinno być owinięte w instrukcję if, aby odfiltrować niepożądane właściwości z prototypu.
Co to znaczy?
javascript
jslint
jrharshath
źródło
źródło
if (evtListeners.hasOwnProperty(ind))
aby ograniczyć przetwarzanie tylko do własnych (nie odziedziczonych) właściwości. Jednak w niektórych przypadkach naprawdę chcesz iterować wszystkie właściwości, w tym te odziedziczone. W takim przypadku JSLint zmusza cię do zawinięcia treści pętli w instrukcji if, aby zdecydować, które właściwości naprawdę chcesz. To zadziała i sprawi, że JSlint będzie szczęśliwy:if (evtListeners[ind] !== undefined)
Odpowiedzi:
Przede wszystkim nigdy nie używaj
for in
pętli do wyliczania tablicy. Nigdy. Użyj starego dobregofor(var i = 0; i<arr.length; i++)
.Przyczyna tego jest następująca: każdy obiekt w JavaScript ma specjalne pole o nazwie
prototype
. Wszystko, co dodasz do tego pola, będzie dostępne dla każdego obiektu tego typu. Załóżmy, że chcesz, aby wszystkie tablice miały nową, fajną funkcjęfilter_0
, która odfiltruje zera.Jest to standardowy sposób rozszerzania obiektów i dodawania nowych metod. Robi to wiele bibliotek. Zobaczmy jednak, jak
for in
teraz działa:Czy ty widzisz? Nagle myśli, że filter_0 to kolejny indeks tablicy. Oczywiście nie jest to tak naprawdę indeks liczbowy, ale
for in
wylicza pola obiektowe, a nie tylko indeksy numeryczne. Wyliczamy teraz za pomocą każdego indeksu liczbowego ifilter_0
. Alefilter_0
nie jest polem żadnego konkretnego obiektu tablicy, każdy obiekt tablicy ma teraz tę właściwość.Na szczęście wszystkie obiekty mają
hasOwnProperty
metodę, która sprawdza, czy to pole naprawdę należy do samego obiektu, czy też jest po prostu dziedziczone z łańcucha prototypów, a zatem należy do wszystkich obiektów tego typu.Zauważ, że chociaż ten kod działa zgodnie z oczekiwaniami dla tablic, nigdy nie powinieneś, nigdy nie używaj
for in
ifor each in
dla tablic. Pamiętaj, żefor in
wylicza pola obiektu, a nie indeksy tablic lub wartości.źródło
for in
do iteracji po tablicach, ponieważ język nie określa kolejności, w jakiejfor in
będzie wyliczany w tablicy. Może nie być w kolejności numerycznej. Ponadto, jeśli użyjesz konstrukcji typu `for (i = 0; i <array.length; i ++), możesz być pewien, że iterujesz tylko indeksy liczbowe w kolejności i nie masz właściwości alfanumerycznych.for-in
pętli (które są świetne, nawiasem mówiąc), powinniśmy edukować ich, jak działają (właściwie zrobione w tej odpowiedzi) i wprowadzić ich, abyObject.defineProperty()
mogli bezpiecznie rozszerzać prototypy, nie niszcząc niczego. Nawiasem mówiąc, rozszerzenie prototypów obiektów rodzimych nie powinno odbywać się bezObject.defineProperty
.Douglas Crockford, autor jslint wiele razy pisał (i mówił) na ten temat. Na tej stronie jego witryny znajduje się sekcja, która obejmuje:
Crockford ma także serię wideo na temat teatru YUI, w której mówi o tym. Seria filmów / rozmów Crockforda na temat javascript jest obowiązkowa, jeśli poważnie myślisz o javascript.
źródło
Źle: (jsHint zgłosi błąd)
Dobry:
źródło
Odpowiedź Vavy jest na znaku. Jeśli używasz jQuery,
$.each()
funkcja się tym zajmuje, dlatego bezpieczniej jest go używać.źródło
$.each
(lub underscore.js_.each
), jeśli można uniknąćfor
pętli raw . jsperf ma kilka testów porównawczych, które warto uruchomić.@all - wszystko w JavaScript jest obiektem (), więc stwierdzenia takie jak „używaj tego tylko na obiektach” są nieco mylące. Ponadto JavaScript nie jest mocno wpisany, więc 1 == „1” jest prawdziwe (chociaż 1 === „1” nie jest, Crockford jest na tym duży). Jeśli chodzi o progromatyczną koncepcję tablic w JS, pisanie jest ważne w definicji.
@Brenton - Nie trzeba być dyktatorem terminologii; „tablica asocjacyjna”, „słownik”, „skrót”, „obiekt”, wszystkie te koncepcje programowania dotyczą jednej struktury w JS. Jest to para nazwa-klucz (indeks, indeks), gdzie wartością może być dowolny inny obiekt (ciągi też są obiektami)
Więc
new Array()
jest taki sam jak[]
new Object()
jest z grubsza podobny do{}
Tworzy strukturę, która jest tablicą z takim ograniczeniem, że wszystkie indeksy (inaczej klucze) muszą być liczbą całkowitą. Pozwala także na automatyczne przypisywanie nowych indeksów przez .push ()
Naprawdę najlepiej jest rozwiązać za pośrednictwem
for(initialization;condition;update){
Ale co z:
Spróbuj tego:
Być może nie najlepsze użycie tablicy, ale tylko ilustracja, że rzeczy nie zawsze są jednoznaczne.
Jeśli znasz swoje klucze, a na pewno nie są to liczby całkowite, jedyną opcją struktury podobnej do tablicy jest obiekt.
źródło
Z pewnością jest to trochę ekstremalne
?
Warto podkreślić sekcję w wyciągu Douglasa Crockforda
Jeśli potrzebujesz tablicy asocjacyjnej (aka hashtable / dictionary), w której klucze są nazywane zamiast indeksowanych numerycznie, będziesz musiał zaimplementować to jako obiekt, np
var myAssocArray = {key1: "value1", key2: "value2"...};
.W takim przypadku
myAssocArray.length
pojawi się zero (ponieważ ten obiekt nie ma właściwości „length”), ai < myAssocArray.length
nie zaprowadzisz cię daleko. Oprócz zapewnienia większej wygody spodziewałbym się, że tablice asocjacyjne będą oferować korzyści wydajnościowe w wielu sytuacjach, ponieważ klucze tablicy mogą być przydatnymi właściwościami (tj. Właściwością lub nazwą identyfikatora członka tablicy), co oznacza, że nie musisz iterować przez długie tablica wielokrotnie oceniająca, czy instrukcje, aby znaleźć pozycję tablicy, której szukasz.W każdym razie, dzięki również za wyjaśnienie komunikatów o błędach JSLint, użyję teraz sprawdzania „isOwnProperty” podczas interakcji z moimi niezliczonymi tablicami asocjacyjnymi!
źródło
length
właściwości, ale można to zrobić w inny sposób:var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
, powinno byćvar myArr = {}
w PHP, są one tym samym, ale nie w JS.Oznacza to, że należy filtrować właściwości evtListeners za pomocą metody hasOwnProperty .
źródło
Aby dodać do tematu for in / for / $. Każdy, dodałem przypadek testowy jsperf do używania $ .each vs for w: http://jsperf.com/each-vs-for-in/2
Różne przeglądarki / wersje radzą sobie z tym inaczej, ale wydaje się, że każdy z nich jest najtańszym rozwiązaniem pod względem wydajności.
Jeśli używasz in w celu iteracji przez asocjacyjną tablicę / obiekt, wiedząc, czego szukasz i ignorując wszystko inne, użyj $ .each, jeśli używasz jQuery, lub tylko dla in (a potem przerwa; po osiągnął, o czym wiesz, że powinien być ostatnim elementem)
Jeśli iterujesz po tablicy, aby wykonać coś z każdą parą kluczy, powinieneś użyć metody hasOwnProperty, jeśli NIE korzystasz z jQuery i użyj $ .each, jeśli używasz jQuery.
Zawsze używaj,
for(i=0;i<o.length;i++)
jeśli nie potrzebujesz tablicy asocjacyjnej, chociaż ... lol chrome wykonał to 97% szybciej niż w przypadku w lub$.each
źródło