it-swarm.com.de

Warum ist die Verwendung von "for ... in" mit Array-Iteration eine schlechte Idee?

Ich wurde angewiesen, for...in mit Arrays in JavaScript nicht zu verwenden. Warum nicht?

1621
lYriCAlsSH

Der Grund ist das eine Konstrukt:

var a = []; // Create a new empty array.
a[5] = 5;   // Perfectly legal JavaScript that resizes the array.

for (var i = 0; i < a.length; i++) {
    // Iterate over numeric indexes from 0 to 5, as everyone expects.
    console.log(a[i]);
}

/* Will display:
   undefined
   undefined
   undefined
   undefined
   undefined
   5
*/

kann sich manchmal völlig von den anderen unterscheiden:

var a = [];
a[5] = 5;
for (var x in a) {
    // Shows only the explicitly set index of "5", and ignores 0-4
    console.log(x);
}

/* Will display:
   5
*/

Beachten Sie auch, dass JavaScript libraries solche Aktionen ausführen kann, die sich auf jedes von Ihnen erstellte Array auswirken:

// Somewhere deep in your JavaScript library...
Array.prototype.foo = 1;

// Now you have no idea what the below code will do.
var a = [1, 2, 3, 4, 5];
for (var x in a){
    // Now foo is a part of EVERY array and 
    // will show up here as a value of 'x'.
    console.log(x);
}

/* Will display:
   0
   1
   2
   3
   4
   foo
*/

1427
Triptych

Die for-in-Anweisung an sich ist keine "schlechte Praxis", sie kann jedoch falsch verwendet sein, z. B. iteriert über Arrays oder arrayähnliche Objekte.

Der Zweck der for-in-Anweisung besteht darin, aufzuzählen über Objekteigenschaften. Diese Anweisung wird in der Prototypkette vorkommen und auch über vererbte -Eigenschaften aufgezählt. Eine Sache, die manchmal nicht erwünscht ist.

Die Reihenfolge der Iteration wird auch nicht von der Spezifikation garantiert. Wenn Sie also ein Array-Objekt "iterieren" möchten, können Sie mit dieser Anweisung nicht sicher sein, dass die Eigenschaften (Array-Indizes) in numerischer Reihenfolge besucht werden.

In JScript (IE <= 8) wird beispielsweise die Reihenfolge der Aufzählung selbst für Array-Objekte definiert, wenn die Eigenschaften erstellt wurden:

var array = [];
array[2] = 'c';
array[1] = 'b';
array[0] = 'a';

for (var p in array) {
  //... p will be "2", "1" and "0" on IE
}

Wenn Sie zum Beispiel das Array.prototype-Objekt erweitern (wie einige Bibliotheken wie MooTools), werden diese Eigenschaften auch aufgezählt:

Array.prototype.last = function () { return this[this.length-1]; };

for (var p in []) { // an empty array
  // last will be enumerated
}

Wie ich bereits vor iterate über Arrays oder Array-ähnlichen Objekten gesagt habe, ist es am besten, einen sequentiellen Loop zu verwenden, wie zum Beispiel einen einfachen alten for/while Schleife.

Wenn Sie nur die eigenen Eigenschaften eines Objekts auflisten möchten (diejenigen, die nicht geerbt sind), können Sie die Methode hasOwnProperty verwenden:

for (var prop in obj) {
  if (obj.hasOwnProperty(prop)) {
    // prop is not inherited
  }
}

Und einige Leute empfehlen sogar, die Methode direkt aus Object.prototype aufzurufen, um Probleme zu vermeiden, wenn jemand unserem Objekt eine Eigenschaft namens hasOwnProperty hinzufügt:

for (var prop in obj) {
  if (Object.prototype.hasOwnProperty.call(obj, prop)) {
    // prop is not inherited
  }
}
364
CMS

Es gibt drei Gründe, warum Sie for..in nicht verwenden sollten, um Array-Elemente zu durchlaufen:

  • for..in wird alle eigenen und geerbten Eigenschaften des Array-Objekts durchlaufen, die nicht DontEnum sind. Das heißt, wenn jemand Eigenschaften zu einem bestimmten Array-Objekt hinzufügt (es gibt gute Gründe dafür - ich habe es selbst getan) oder Array.prototype geändert (was als schlechte Praxis in Code betrachtet wird, der mit anderen Skripten gut funktionieren sollte), diese Eigenschaften wird auch wiederholt werden; Vererbte Eigenschaften können durch Aktivieren von hasOwnProperty() ausgeschlossen werden. Dies hilft Ihnen jedoch nicht bei Eigenschaften, die im Array-Objekt selbst festgelegt sind

  • Es wird nicht garantiert, dass for..in die Elementreihenfolge beibehält

  • es ist langsam, weil Sie alle Eigenschaften des Array-Objekts und seiner gesamten Prototypkette durchlaufen müssen und immer noch nur den Namen der Eigenschaft erhalten. Um den Wert zu erhalten, ist eine zusätzliche Suche erforderlich

107
Christoph

Denn für ... zählt das Objekt, in dem sich das Array befindet, und nicht das Array selbst auf. Wenn ich der Prototypenkette der Arrays eine Funktion hinzufüge, wird diese ebenfalls aufgenommen. Das heißt.

Array.prototype.myOwnFunction = function() { alert(this); }
a = new Array();
a[0] = 'foo';
a[1] = 'bar';
for(x in a){
 document.write(x + ' = ' + a[x]);
}

Dies wird schreiben:

 0 = foo 
 1 = bar 
 MyOwnFunction = function () {alert (this); } 

Und da Sie nie sicher sein können, dass nichts zur Prototypkette hinzugefügt wird, verwenden Sie einfach eine for-Schleife, um das Array aufzulisten:

for(i=0,x=a.length;i<x;i++){
 document.write(i + ' = ' + a[i]);
}

Dies wird schreiben:

 0 = foo 
 1 = bar 
50
Pim Jager

Es ist nichts dagegen einzuwenden, For-In für Arrays zu verwenden. For-in durchläuft die Eigenschaftsnamen eines Objekts und im Falle eines "out-of-the-box" -Arrays entsprechen die Eigenschaften den Array-Indizes. (Die integrierten Eigenschaften wie length, toString usw. sind nicht in der Iteration enthalten.)

Wenn Ihr Code (oder das von Ihnen verwendete Framework) jedoch benutzerdefinierte Eigenschaften zu Arrays oder zum Prototyp des Arrays hinzufügt, werden diese Eigenschaften in die Iteration einbezogen, was wahrscheinlich nicht Ihren Vorstellungen entspricht.

Einige JS-Frameworks wie Prototype modifizieren den Array-Prototyp. Andere Frameworks wie JQuery nicht, daher können Sie mit JQuery for-in verwenden.

Wenn Sie Zweifel haben, sollten Sie wahrscheinlich kein In-In verwenden. 

Eine alternative Methode zum Durchlaufen eines Arrays ist die Verwendung einer for-Schleife:

for (var ix=0;ix<arr.length;ix++) alert(ix);

Dies hat jedoch ein anderes Problem. Das Problem ist, dass ein JavaScript-Array "Löcher" haben kann. Wenn Sie arr definieren als:

var arr = ["hello"];
arr[100] = "goodbye";

Dann hat das Array zwei Elemente, aber eine Länge von 101. Die Verwendung von for-in ergibt zwei Indizes, während die for-Schleife 101 Indizes ergibt, wobei 99 den Wert undefined hat.

38
JacquesB

Zusätzlich zu den in anderen Antworten angegebenen Gründen möchten Sie möglicherweise nicht die "for ... in" - Struktur verwenden, wenn Sie mit der counter-Variablen rechnen müssen, da die Schleife die Namen der Objekteigenschaften und somit die Variable durchläuft ist eine Zeichenfolge.

Zum Beispiel,

for (var i=0; i<a.length; i++) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

werde schreiben 

0, number, 1
1, number, 2
...

wohingegen,

for (var ii in a) {
    document.write(i + ', ' + typeof i + ', ' + i+1);
}

werde schreiben

0, string, 01
1, string, 11
...

Natürlich kann dies leicht durch Einschließen überwunden werden

ii = parseInt(ii);

in der Schleife, aber die erste Struktur ist direkter.

30
ctmiddle

Ab 2016 (ES6) können wir for…of für die Array-Iteration verwenden, wie John Slegers bereits bemerkt hat. 

Ich möchte nur diesen einfachen Demonstrationscode hinzufügen, um die Dinge klarer zu machen:

Array.prototype.foo = 1;
var arr = [];
arr[5] = "xyz";

console.log("for...of:");
var count = 0;
for (var item of arr) {
    console.log(count + ":", item);
    count++;
    }

console.log("for...in:");
count = 0;
for (var item in arr) {
    console.log(count + ":", item);
    count++;
    }

Die Konsole zeigt:

for...of:

0: undefined
1: undefined
2: undefined
3: undefined
4: undefined
5: xyz

for...in:

0: 5
1: foo

Mit anderen Worten:

  • for...of zählt von 0 bis 5 und ignoriert auch Array.prototype.foo. Es zeigt Array Werte .

  • for...in listet nur den 5 auf, wobei undefinierte Array-Indizes ignoriert werden, jedoch foo hinzugefügt wird. Es zeigt Array Eigenschaftsnamen .

29
MarcG

Abgesehen von der Tatsache, dass for...in über alle aufzählbaren Eigenschaften hinwegläuft (was nicht und "alle Array-Elemente" entspricht!), Siehe http://www.ecma-international.org/ Publikationen/Dateien/ECMA-ST/Ecma-262.pdf , Abschnitt 12.6.4 (5. Auflage) oder 13.7.5.15 (7. Auflage):

Die Mechanik und order der Aufzählung der Eigenschaften ... ist nicht angegeben ...

(Betonung mein.)

Das heißt, wenn ein Browser dies wünscht, könnte er die Eigenschaften in der Reihenfolge durchgehen, in der sie eingefügt wurden. Oder in numerischer Reihenfolge. Oder in lexikalischer Reihenfolge (wobei "30" vor "4" steht! Denken Sie daran, dass alle Objektschlüssel - und damit alle Array-Indizes - tatsächlich Strings sind, so dass es absolut sinnvoll ist). Sie könnten sie per Bucket durchlaufen, wenn sie Objekte als Hashtabellen implementieren. Oder nehmen Sie irgendetwas davon und fügen Sie "rückwärts" hinzu. Ein Browser könnte sogar zufällig iterieren [] und ECMA-262-konform sein, solange er jede Eigenschaft genau einmal besucht hat.

In der Praxis durchlaufen die meisten Browser derzeit in etwa die gleiche Reihenfolge. Aber es gibt nichts zu sagen, dass sie müssen. Das ist implementierungsspezifisch und kann sich jederzeit ändern, wenn sich herausstellt, dass ein anderer Weg weitaus effizienter ist.

In jedem Fall trägt for...in keine Konnotation der Reihenfolge. Wenn Sie Interesse an der Reihenfolge haben, machen Sie dies ausdrücklich und verwenden Sie eine normale for-Schleife mit einem Index.

22
cHao

Kurze Antwort: Es lohnt sich einfach nicht.


Längere Antwort: Es lohnt sich einfach nicht, auch wenn die Reihenfolge der Elemente und die optimale Leistung nicht erforderlich sind.


Lange Antwort: Es lohnt sich aus folgenden Gründen nicht:

  • Die Verwendung von for (var i in array) {} führt dazu, dass 'array' als jedes andere pure - Objekt interpretiert wird, die Objektkette durchquert und letztendlich langsamer als eine indexbasierte for-Schleife arbeitet.
  • Es kann nicht garantiert werden, dass die Objekteigenschaften in der angegebenen Reihenfolge zurückgegeben werden.
  • Die Verwendung von hasOwnProperty()- oder isNaN()-Prüfungen zum Filtern der Objekteigenschaften ist ein zusätzlicher Aufwand, der dazu führt, dass das Objekt (noch langsamer) langsamer ausgeführt wird. Durch das Einführen einer solchen zusätzlichen Logik wird auch der Hauptgrund für die Verwendung dieser Logik negiert, d. H. Aufgrund des knapperen Formats.

Aus diesen Gründen gibt es keinen akzeptablen Kompromiss zwischen Leistung und Komfort. Es ist wirklich kein Vorteil, es sei denn, es ist beabsichtigt, das Array als pure - Objekt zu behandeln und Operationen an den Eigenschaften des Array-Objekts auszuführen.

21
WynandB

Weil es durch Objektfelder und nicht durch Indizes aufgezählt wird. Sie können Wert mit Index "Länge" erhalten und ich bezweifle, dass Sie dies wollen.

15
vava

Hauptsächlich zwei Gründe:

Ein

Wie andere bereits gesagt haben, erhalten Sie möglicherweise Schlüssel, die sich nicht in Ihrem Array befinden oder vom Prototyp übernommen werden. Wenn also eine Bibliothek zu den Prototypen von Array oder Object eine Eigenschaft hinzufügt:

Array.prototype.someProperty = true

Sie erhalten es als Teil jedes Arrays:

for(var item in [1,2,3]){
  console.log(item) // will log 1,2,3 but also "someProperty"
}

sie könnten dies mit der Methode hasOwnProperty lösen:

var ary = [1,2,3];
for(var item in ary){
   if(ary.hasOwnProperty(item)){
      console.log(item) // will log only 1,2,3
   }
}

dies gilt jedoch für das Durchlaufen aller Objekte mit einer for-in-Schleife.

Zwei

Normalerweise ist die Reihenfolge der Elemente in einem Array wichtig, aber die For-in-Schleife wird nicht notwendigerweise in der richtigen Reihenfolge durchlaufen, da das Array als Objekt behandelt wird. Dies ist die Art, wie es in JS implementiert ist, und nicht als Array ... Dies scheint eine kleine Sache zu sein, aber es kann Anwendungen wirklich vermasseln und ist schwer zu debuggen.

15
Lior

Das Problem mit for ... in ... - und dies wird nur dann ein Problem, wenn ein Programmierer die Sprache nicht wirklich versteht. Es ist nicht wirklich ein Fehler oder irgendetwas - ist, dass es all Member eines Objekts durchläuft (na ja, alle Enumerable Member, aber das ist jetzt ein Detail). Wenn Sie die indizierten Eigenschaften eines Arrays durch nur iterieren möchten, können Sie die semantische Konsistenz nur garantieren, wenn Sie einen Ganzzahlindex (d. H. Eine for (var i = 0; i < array.length; ++i) style-Schleife) verwenden.

Jedem Objekt können beliebige Eigenschaften zugeordnet sein. Insbesondere beim Laden zusätzlicher Eigenschaften in eine Array-Instanz wäre nichts Schlimmes. Code, der nur indizierte Array-ähnliche Eigenschaften anzeigen möchte, daher must an einem Ganzzahlindex bleiben. Code, der sich voll bewusst ist, was for ... in tut, und need, um alle Eigenschaften anzuzeigen. Nun, das ist auch in Ordnung.

14
Pointy

Ich glaube nicht, dass ich viel hinzufügen kann. Triptychons Antwort oder CMS's Antwort Warum sollte for-in in einigen Fällen vermieden werden?.

Ich möchte jedoch hinzufügen, dass in modernen Browsern es eine Alternative zu for-in gibt, die in jenen Fällen verwendet werden kann, in denen for-in nicht verwendet werden kann. Diese Alternative ist for-of :

for (var item of items) {
    console.log(item);
}

Hinweis :

Leider unterstützt keine Version von Internet Explorer diese Funktion ( Edge 12+ tut). Sie müssen also etwas länger warten, bis Sie sie in Ihrem clientseitigen Produktionscode verwenden können. Es sollte jedoch sicher sein, in Ihrem serverseitigen JS-Code verwendet zu werden (wenn Sie Node.js verwenden).

10
John Slegers

Aufgrund der Semantik ist die Art und Weise, wie for, in Arrays behandelt (d. H. Genauso wie jedes andere JavaScript-Objekt), nicht mit anderen gängigen Sprachen ausgerichtet.

// C#
char[] a = new char[] {'A', 'B', 'C'};
foreach (char x in a) System.Console.Write(x); //Output: "ABC"

// Java
char[] a = {'A', 'B', 'C'};
for (char x : a) System.out.print(x);          //Output: "ABC"

// PHP
$a = array('A', 'B', 'C');
foreach ($a as $x) echo $x;                    //Output: "ABC"

// JavaScript
var a = ['A', 'B', 'C'];
for (var x in a) document.write(x);            //Output: "012"
8
matpop

Neben den anderen Problemen ist die Syntax "for..in" wahrscheinlich langsamer, da der Index eine Zeichenfolge und keine Ganzzahl ist.

var a = ["a"]
for (var i in a)
    alert(typeof i)  // 'string'
for (var i = 0; i < a.length; i++)
    alert(typeof i)  // 'number'
7
dc1

Ein wichtiger Aspekt ist, dass for...in nur Eigenschaften durchläuft, die in einem Objekt enthalten sind und deren enumerable property-Attribut auf true gesetzt ist. Wenn also versucht wird, ein Objekt mit for...in zu iterieren, können beliebige Eigenschaften fehlen, wenn das Enumerable-Eigenschaftsattribut false ist. Es ist durchaus möglich, das aufzählbare Eigenschaftenattribut für normale Array-Objekte so zu ändern, dass bestimmte Elemente nicht aufgelistet werden. Im Allgemeinen gelten die Eigenschaftsattribute jedoch für Funktionseigenschaften innerhalb eines Objekts.

Sie können den Wert des Eigenschaftsattributs einer Eigenschaft für Aufzählungen folgendermaßen überprüfen:

myobject.propertyIsEnumerable('myproperty')

Oder um alle vier Eigenschaftsattribute zu erhalten:

Object.getOwnPropertyDescriptor(myobject,'myproperty')

Dies ist eine in ECMAScript 5 verfügbare Funktion. In früheren Versionen war es nicht möglich, den Wert des Eigenschaftsattributs "Enumerable" zu ändern (es wurde immer auf "true" gesetzt).

7
Pierz

for/in arbeitet mit zwei Variablentypen: Hashtabellen (assoziative Arrays) und Array (nicht assoziativ).

JavaScript legt automatisch fest, auf welche Weise die Artikel durchlaufen werden. Wenn Sie also wissen, dass Ihr Array wirklich nicht assoziativ ist, können Sie for (var i=0; i<=arrayLen; i++) verwenden und die automatische Erkennung der Iteration überspringen.

Meiner Meinung nach ist es jedoch besser, for/in zu verwenden. Der für diese automatische Erkennung erforderliche Prozess ist sehr klein. 

Eine echte Antwort darauf hängt davon ab, wie der Browser den JavaScript-Code analysiert/interpretiert. Es kann zwischen Browsern wechseln.

Ich kann mir keine anderen Zwecke vorstellen, for/in zu verwenden.

//Non-associative
var arr = ['a', 'b', 'c'];
for (var i in arr)
   alert(arr[i]);

//Associative
var arr = {
   item1 : 'a',
   item2 : 'b',
   item3 : 'c'
};

for (var i in arr)
   alert(arr[i]);
7
Ricardo

TL & DR: Die Verwendung der for in-Schleife in Arrays ist nicht böse, im Gegenteil.

Ich denke, die for in-Schleife ist ein Juwel von JS, wenn richtig in Arrays verwendet wird. Es wird von Ihnen erwartet, dass Sie die vollständige Kontrolle über Ihre Software haben und wissen, was Sie tun. Sehen wir uns die erwähnten Nachteile an und widerlegen Sie sie einzeln.

  1. Es durchläuft auch geerbte Eigenschaften: Zunächst sollten alle Erweiterungen von Array.prototype mit Object.defineProperty() durchgeführt werden, und ihr enumerable-Deskriptor sollte auf false gesetzt sein. Jede Bibliothek, die dies nicht tut, sollte überhaupt nicht verwendet werden.
  2. Eigenschaften, die Sie später zur Vererbungskette hinzufügen, werden gezählt: Bei der Subklassifizierung von Arrays durch Object.setPrototypeOf oder durch Klasse extend. Sie sollten erneut Object.defineProperty() verwenden, wodurch standardmäßig die Eigenschaftsdeskriptoren writable, enumerable und configurable auf false gesetzt werden. Hier sehen Sie ein Beispiel für die Unterklassifizierung von Arrays ...

function Stack(...a){
  var stack = new Array(...a);
  Object.setPrototypeOf(stack, Stack.prototype);
  return stack;
}
Stack.prototype = Object.create(Array.prototype);                                 // now stack has full access to array methods.
Object.defineProperty(Stack.prototype,"constructor",{value:Stack});               // now Stack is a proper constructor
Object.defineProperty(Stack.prototype,"peak",{value: function(){                  // add Stack "only" methods to the Stack.prototype.
                                                       return this[this.length-1];
                                                     }
                                             });
var s = new Stack(1,2,3,4,1);
console.log(s.peak());
s[s.length] = 7;
console.log("length:",s.length);
s.Push(42);
console.log(JSON.stringify(s));
console.log("length:",s.length);

for(var i in s) console.log(s[i]);

Sie sehen also ... for in loop ist jetzt sicher, da Sie sich um Ihren Code gekümmert haben.

  1. Die for in-Schleife ist langsam: Hell no. Es ist bei weitem die schnellste Methode der Iteration, wenn Sie spärliche Arrays durchlaufen, die von Zeit zu Zeit benötigt werden. Dies ist einer der wichtigsten Performance-Tricks, die man kennen sollte. Lassen Sie uns ein Beispiel sehen. Wir werden ein spärliches Array durchlaufen.

var a = [];
a[0] = "zero";
a[10000000] = "ten million";
console.time("for loop on array a:");
for(var i=0; i < a.length; i++) a[i] && console.log(a[i]);
console.timeEnd("for loop on array a:");
console.time("for in loop on array a:");
for(var i in a) a[i] && console.log(a[i]);
console.timeEnd("for in loop on array a:");

7
Redu

Wenn Sie nicht aufpassen, werden Eigenschaften, die zu Objekten in der Prototypkette gehören, durchlaufen.

Sie können for.. in verwenden. Achten Sie darauf, jede Eigenschaft mit hasOwnProperty zu überprüfen.

6
JAL

Es ist nicht unbedingt schlecht (basierend auf dem, was Sie tun), aber wenn Sie Arrays mit Array.prototype versehen haben, erhalten Sie seltsame Ergebnisse. Wo würden Sie erwarten, dass diese Schleife dreimal ausgeführt wird:

var arr = ['a','b','c'];
for (var key in arr) { ... }

Wenn eine Funktion namens helpfulUtilityMethod zu Arrays prototype hinzugefügt wurde, läuft Ihre Schleife viermal: key wäre 0, 1, 2 und helpfulUtilityMethod. Wenn Sie nur ganze Zahlen erwartet haben, oops.

5
josh3736

Sie sollten for(var x in y) nur für Eigenschaftslisten verwenden, nicht für Objekte (wie oben beschrieben).

5
user268396

Die for...in-Schleife für ein Array zu verwenden, ist nicht falsch, obwohl ich vermuten kann, warum jemand Ihnen das gesagt hat:

1.) Es gibt bereits eine Funktion oder Methode höherer Ordnung, die diesen Zweck für ein Array hat, jedoch mehr Funktionalität und eine schlankere Syntax hat, die als 'forEach' bezeichnet wird: Array.prototype.forEach(function(element, index, array) {} );

2.) Arrays haben immer eine Länge, aber for...in und forEach führen keine Funktion für jeden Wert aus, der 'undefined' ist, nur für die Indizes, für die ein Wert definiert ist. Wenn Sie also nur einen Wert zuweisen, führen diese Schleifen eine Funktion nur einmal aus. Da ein Array jedoch aufgezählt wird, hat es immer eine Länge bis zum höchsten Index, der einen definierten Wert hat. Diese Länge kann jedoch bei Verwendung dieser Werte unbemerkt bleiben Schleifen.

3.) Der Standard für Schleife führt eine Funktion so oft aus, wie Sie in den Parametern definieren. Da ein Array nummeriert ist, ist es sinnvoller zu definieren, wie oft Sie eine Funktion ausführen möchten. Im Gegensatz zu den anderen Schleifen kann die for-Schleife dann für jeden Index im Array eine Funktion ausführen, unabhängig davon, ob der Wert definiert ist oder nicht.

Im Wesentlichen können Sie eine beliebige Schleife verwenden, sollten sich aber genau erinnern, wie sie funktioniert. Verstehen Sie die Bedingungen, unter denen die verschiedenen Schleifen wiederholt werden, sowie deren separate Funktionen und erkennen Sie, dass sie für unterschiedliche Szenarien mehr oder weniger geeignet sind. 

Die Verwendung der forEach -Methode als generell der for...in-Schleife kann als eine bessere Praxis betrachtet werden, da sie einfacher zu schreiben ist und über mehr Funktionen verfügt. Daher sollten Sie sich angewöhnen, nur diese Methode und diesen Standard zu verwenden. aber dein Anruf.

Unten sehen Sie, dass die ersten beiden Schleifen die Anweisungen von console.log nur einmal ausführen, während der Standard für die Schleife die Funktion so oft ausführt, wie angegeben, in diesem Fall array.length = 6.

var arr = [];
arr[5] = 'F';

for (var index in arr) {
console.log(index);
console.log(arr[index]);
console.log(arr)
}
// 5
// 'F'
// => (6) [undefined x 5, 6]

arr.forEach(function(element, index, arr) {
console.log(index);
console.log(element);
console.log(arr);
});
// 5
// 'F'
// => Array (6) [undefined x 5, 6]

for (var index = 0; index < arr.length; index++) {
console.log(index);
console.log(arr[index]);
console.log(arr);
};
// 0
// undefined
// => Array (6) [undefined x 5, 6]

// 1
// undefined
// => Array (6) [undefined x 5, 6]

// 2
// undefined
// => Array (6) [undefined x 5, 6]

// 3
// undefined
// => Array (6) [undefined x 5, 6]

// 4
// undefined
// => Array (6) [undefined x 5, 6]

// 5
// 'F'
// => Array (6) [undefined x 5, 6]
3
mrmaclean89

Eine for ... in-Schleife führt immer die Schlüssel auf. Objekteigenschaften Schlüssel sind immer String, selbst die indizierten Eigenschaften eines Arrays:

var myArray = ['a', 'b', 'c', 'd'];
var total = 0
for (elem in myArray) {
  total += elem
}
console.log(total); // 00123
2
Maher Tliba

Hier sind die Gründe, warum dies (normalerweise) eine schlechte Praxis ist:

  1. for...in -Schleifen durchlaufen alle ihre eigenen aufzählbaren Eigenschaften nd die aufzählbaren Eigenschaften ihrer Prototypen. Normalerweise möchten wir in einer Array-Iteration nur das Array selbst durchlaufen. Und obwohl Sie dem Array möglicherweise selbst nichts hinzufügen, fügen Ihre Bibliotheken oder Ihr Framework möglicherweise etwas hinzu.

Beispiel:

Array.prototype.hithere = 'hithere';

var array = [1, 2, 3];
for (let el in array){
    // the hithere property will also be iterated over
    console.log(el);
}
  1. for...in Schleifen garantieren keine bestimmte Iterationsreihenfolge. Obwohl diese Reihenfolge heutzutage in den meisten modernen Browsern zu finden ist, gibt es noch keine 100% ige Garantie.
  2. for...in Schleifen ignorieren undefined Array-Elemente, d. H. Array-Elemente, die noch nicht zugewiesen wurden.

Beispiel::

const arr = []; 
arr[3] = 'foo';   // resize the array to 4
arr[4] = undefined; // add another element with value undefined to it

// iterate over the array, a for loop does show the undefined elements
for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
}

console.log('\n');

// for in does ignore the undefined elements
for (let el in arr) {
    console.log(arr[el]);
}
2

for ... in ist nützlich, wenn Sie mit einem Objekt in JavaScript arbeiten, jedoch nicht für ein Array. Wir können jedoch nicht sagen, dass dies ein falscher Weg ist. Es wird jedoch nicht empfohlen. Schauen Sie sich dieses Beispiel mit for an ... in der Schleife:

let txt = "";
const person = {fname:"Alireza", lname:"Dezfoolian", age:35}; 
for (const x in person) {
    txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

OK, lass es uns jetzt mit Array machen:

let txt = "";
const person = ["Alireza", "Dezfoolian", 35]; 
for (const x in person) {
   txt += person[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 

Da siehst du das Ergebnis gleich ...

Aber lass uns etwas versuchen, lass uns etwas zu Array prototypisieren ...

Array.prototype.someoneelse = "someoneelse";

Jetzt erstellen wir ein neues Array ();

let txt = "";
const arr = new Array();
arr[0] = 'Alireza';
arr[1] = 'Dezfoolian';
arr[2] = 35;
for(x in arr) {
 txt += arr[x] + " ";
}
console.log(txt); //Alireza Dezfoolian 35 someoneelse

Sie sehen das someoneelse !!! ... In diesem Fall durchlaufen wir tatsächlich ein neues Array-Objekt!

Das ist einer der Gründe, warum wir for..in sorgfältig verwenden müssen, aber das ist nicht immer der Fall ...

1
Alireza

Da JavaScript-Elemente als Standardobjekteigenschaften gespeichert werden, ist es Es ist nicht ratsam, JavaScript-Arrays mit für ... in .__ zu durchlaufen. Schleifen, da normale Elemente und alle aufzählbaren Eigenschaften .__ sein werden. aufgelistet.

Von https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections

0
Badr Elmers

obwohl durch diese Frage nicht speziell angesprochen, möchte ich hinzufügen, dass es einen sehr guten Grund gibt, niemals ... in einer NodeList zu verwenden (wie man es von einem querySelectorAll-Aufruf erhalten würde, da die zurückgegebenen Elemente überhaupt nicht angezeigt werden , stattdessen nur über die NodeList-Eigenschaften iterieren.

im Falle eines einzigen Ergebnisses bekam ich:

var nodes = document.querySelectorAll(selector);
nodes
▶ NodeList [a._19eb]
for (node in nodes) {console.log(node)};
VM505:1 0
VM505:1 length
VM505:1 item
VM505:1 entries
VM505:1 forEach
VM505:1 keys
VM505:1 values

was erklärt, warum meine for (node in nodes) node.href = newLink; fehlgeschlagen ist.

0
jcomeau_ictx