Ich habe JSLint für eine meiner JavaScript-Dateien verwendet. Es warf den Fehler:
for( ind in evtListeners ) {
Problem in Zeile 41, Zeichen 9: Der Text eines for in sollte in eine if-Anweisung eingeschlossen werden, um unerwünschte Eigenschaften aus dem Prototyp herauszufiltern.
Was bedeutet das?
javascript
jslint
jrharshath
quelle
quelle
if (evtListeners.hasOwnProperty(ind))
um die Verarbeitung nur auf eigene (nicht vererbte) Eigenschaften zu beschränken. In einigen Fällen möchten Sie jedoch wirklich alle Eigenschaften durchlaufen, einschließlich der geerbten. In diesem Fall zwingt JSLint Sie, den Schleifenkörper in eine if-Anweisung zu packen, um zu entscheiden, welche Eigenschaften Sie wirklich möchten. Dies wird funktionieren und JSlint glücklich machen:if (evtListeners[ind] !== undefined)
Antworten:
Zunächst einmal, nie eine Verwendung
for in
Schleife ein Array aufzählen über. Noch nie. Verwenden Sie gute altefor(var i = 0; i<arr.length; i++)
.Der Grund dafür ist folgender: Jedes Objekt in JavaScript hat ein spezielles Feld namens
prototype
. Alles, was Sie diesem Feld hinzufügen, ist für jedes Objekt dieses Typs zugänglich. Angenommen, Sie möchten, dass alle Arrays eine coole neue Funktion habenfilter_0
, die Nullen herausfiltert.Dies ist eine Standardmethode zum Erweitern von Objekten und Hinzufügen neuer Methoden. Viele Bibliotheken tun dies. Schauen wir uns jedoch an, wie es
for in
jetzt funktioniert:Siehst du? Es denkt plötzlich, dass filter_0 ein weiterer Array-Index ist. Natürlich ist es nicht wirklich ein numerischer Index, sondern
for in
zählt durch Objektfelder auf, nicht nur durch numerische Indizes. Also zählen wir jetzt jeden numerischen Index auf undfilter_0
. Istfilter_0
aber kein Feld eines bestimmten Array-Objekts, hat jedes Array-Objekt jetzt diese Eigenschaft.Glücklicherweise haben alle Objekte eine
hasOwnProperty
Methode, die prüft, ob dieses Feld wirklich zum Objekt selbst gehört oder ob es einfach von der Prototypenkette geerbt wird und somit zu allen Objekten dieses Typs gehört.Beachten Sie, dass dieser Code, obwohl er für Arrays wie erwartet funktioniert, niemals, niemals funktionieren sollte , Verwendung
for in
undfor each in
für Arrays. Denken Sie daran, dassfor in
die Felder eines Objekts aufgelistet werden, nicht Array-Indizes oder -Werte.quelle
for in
zum Durchlaufen von Arrays verwenden, da die Sprache nicht die Reihenfolge angibt, in derfor in
die Aufzählung über ein Array erfolgt. Möglicherweise ist es nicht in numerischer Reihenfolge. Wenn Sie außerdem das Konstrukt `for (i = 0; i <array.length; i ++) verwenden, können Sie sicher sein, dass Sie nur numerische Indizes in der angegebenen Reihenfolge und keine alphanumerischen Eigenschaften iterieren.for-in
Schleifen abzuhalten (die übrigens fantastisch sind), sollten wir sie über ihre Funktionsweise informieren (in dieser Antwort richtig gemacht) und sie vorstellen,Object.defineProperty()
damit sie ihre Prototypen sicher erweitern können, ohne etwas zu beschädigen. Im Übrigen sollte auf die Erweiterung der Prototypen nativer Objekte nicht verzichtet werdenObject.defineProperty
.Douglas Crockford, der Autor von jslint, hat viele Male über dieses Thema geschrieben (und gesprochen). Auf dieser Seite seiner Website gibt es einen Abschnitt, der Folgendes behandelt:
Crockford hat auch eine Videoserie über das YUI-Theater, in der er darüber spricht. Crockfords Reihe von Videos / Vorträgen über Javascript ist ein Muss, wenn Sie Javascript überhaupt ernst nehmen.
quelle
Schlecht: (jsHint gibt einen Fehler aus)
Gut:
quelle
Die Antwort von Vava ist genau richtig. Wenn Sie jQuery verwenden,
$.each()
kümmert sich die Funktion darum, daher ist die Verwendung sicherer.quelle
$.each
(oder underscore.js_.each
) zu verwenden, wenn Sie mit der Rohschleife davonkommen könnenfor
. jsperf hat einige augenöffnende Vergleichstests, die es wert sind, ausgeführt zu werden.@all - alles in JavaScript ist ein Objekt (), daher sind Aussagen wie "Nur für Objekte verwenden" etwas irreführend. Außerdem ist JavaScript nicht stark typisiert, so dass 1 == "1" wahr ist (obwohl 1 === "1" nicht wahr ist, ist Crockford in dieser Hinsicht groß). Wenn es um das progressive Konzept von Arrays in JS geht, ist die Eingabe bei der Definition wichtig.
@Brenton - Sie müssen kein Terminologiediktator sein. "assoziatives Array", "Wörterbuch", "Hash", "Objekt", diese Programmierkonzepte gelten alle für eine Struktur in JS. Es handelt sich um Namenswertpaare (Schlüssel, Index), bei denen der Wert ein beliebiges anderes Objekt sein kann (Zeichenfolgen sind ebenfalls Objekte).
Also
new Array()
ist das gleiche wie[]
new Object()
ist ungefähr ähnlich zu{}
Erstellt eine Struktur, die ein Array mit der Einschränkung ist, dass alle Indizes (auch als Schlüssel bezeichnet) eine ganze Zahl sein müssen. Es ermöglicht auch die automatische Zuweisung neuer Indizes über .push ()
Wird in der Tat am besten über behandelt
for(initialization;condition;update){
Aber was ist mit:
Versuche dies:
Vielleicht nicht die beste Verwendung eines Arrays, sondern nur ein Beispiel dafür, dass die Dinge nicht immer eindeutig sind.
Wenn Sie Ihre Schlüssel kennen und definitiv keine ganzen Zahlen sind, ist das Objekt Ihre einzige Array-ähnliche Strukturoption.
quelle
Sicher ist es ein bisschen extrem zu sagen
?
Es lohnt sich, den Abschnitt im Douglas Crockford-Auszug hervorzuheben
Wenn Sie ein assoziatives Array (auch bekannt als Hashtable / Dictionary) benötigen, in dem Schlüssel anstelle von numerisch indiziert benannt werden, müssen Sie dies als Objekt implementieren, z
var myAssocArray = {key1: "value1", key2: "value2"...};
.In diesem Fall
myAssocArray.length
wird null angezeigt (da dieses Objekt keine Eigenschaft 'length' hat), und Siei < myAssocArray.length
werden nicht sehr weit kommen. Ich würde erwarten, dass assoziative Arrays nicht nur mehr Komfort bieten, sondern in vielen Situationen auch Leistungsvorteile bieten, da die Array-Schlüssel nützliche Eigenschaften sein können (dh die ID-Eigenschaft oder der Name eines Array-Mitglieds), sodass Sie nicht lange durchlaufen müssen Das Array prüft wiederholt, ob Anweisungen vorhanden sind, um den gewünschten Array-Eintrag zu finden.Wie auch immer, danke auch für die Erklärung der JSLint-Fehlermeldungen, ich werde jetzt die 'isOwnProperty'-Prüfung verwenden, wenn ich über meine unzähligen assoziativen Arrays interagiere!
quelle
length
Eigenschaft haben, aber Sie können es auf andere Weise tun:var myArr = []; myArr['key1'] = 'hello'; myArr['key2'] = 'world';
var myArr = []
.var myArr = {}
In PHP sollten sie dasselbe sein, aber nicht in JS.Dies bedeutet, dass Sie die Eigenschaften von evtListeners mit der hasOwnProperty-Methode filtern sollten .
quelle
Um das Thema for in / for / $. Zu ergänzen, habe ich einen jsperf-Testfall für die Verwendung von $ .each vs for in hinzugefügt: http://jsperf.com/each-vs-for-in/2
Verschiedene Browser / Versionen behandeln es unterschiedlich, aber es scheint, dass $ .each und direkt für in die leistungsmäßig günstigsten Optionen sind.
Wenn Sie for in verwenden, um ein assoziatives Array / Objekt zu durchlaufen, wissen, wonach Sie suchen, und alles andere ignorieren, verwenden Sie $ .each, wenn Sie jQuery verwenden, oder nur for in (und dann eine Pause; sobald Sie dies getan haben) erreicht, was Sie wissen, sollte das letzte Element sein)
Wenn Sie durch ein Array iterieren, um mit jedem Schlüsselpaar etwas auszuführen, sollten Sie die hasOwnProperty-Methode verwenden, wenn Sie jQuery NICHT verwenden, und $ .each verwenden, wenn Sie jQuery verwenden.
Immer verwenden,
for(i=0;i<o.length;i++)
wenn Sie kein assoziatives Array benötigen ... lol chrome hat das 97% schneller ausgeführt als ein for in oder$.each
quelle