Was ist der Unterschied zwischen (für… in) und (für… von) Anweisungen in JavaScript?

410

Ich weiß, was eine for... inSchleife ist (sie iteriert über den Schlüssel), habe aber beim ersten Mal davon gehört for... of(sie iteriert über den Wert).

Ich bin mit for... ofSchleife verwechselt . Ich habe kein Adjektiv bekommen. Dies ist der folgende Code:

var arr = [3, 5, 7];
arr.foo = "hello";

for (var i in arr) {
  console.log(i); // logs "0", "1", "2", "foo"
}

for (var i of arr) {
  console.log(i); // logs "3", "5", "7"
  // it is does not log "3", "5", "7", "hello"
}

Was ich habe, ist, for... ofiteriert über Eigenschaftswerte. Warum loggt es nicht (zurück) "3", "5", "7", "hello"statt "3", "5", "7"? Die for... inSchleife durchläuft jedoch jede Taste ( "0", "1", "2", "foo"). Hier for... initeriert die Schleife auch über den fooSchlüssel. Aber for... ofiteriert nicht über den Wert von fooEigentum dh "hello". Warum ist es so?

Lange Rede, kurzer Sinn:

Hier tröste ich for... ofSchleife. Es sollte sich protokollieren, "3", "5", "7","hello"aber hier wird es protokolliert "3", "5", "7". Warum ?

Beispiel Link

Mukund Kumar
quelle
1
Für den Fall, dass Sie es verpassen, ist hier der Inception-Link developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Anthony Russell
1
Soweit ich weiß, for ... ofwurde es in die Sprache gebracht, um die Probleme bei der Verwendung for ... inmit Arrays zu beheben . Array.prototypekönnte so geändert werden, dass zusätzliche Eigenschaften verfügbar sind, was es unsicher macht, sie zu wiederholen, da Sie möglicherweise nicht numerische Schlüssel erhalten, die Sie nicht erwartet haben.
Phylogenesis
2
Für zukünftige Leser: Dies ist wahrscheinlich kein Duplikat des JavaScript- ofSchlüsselworts (für… von Schleifen) , da es nach einem bestimmten Verhalten der Funktion fragt, anstatt nach einer allgemeinen Übersicht zu fragen.
Apsiller
2
for <key> infor <value> offor..of
Gewöhnen Sie sich
Großartiger Artikel über enumerable medium.com/@shivamethical/…
Kalhan.Toress

Antworten:

304

for in Schleifen über aufzählbare Eigenschaftsnamen eines Objekts.

for of(neu in ES6) verwendet einen objektspezifischen Iterator und durchläuft die dadurch generierten Werte.

In Ihrem Beispiel liefert der Array-Iterator alle Werte im Array (ohne Berücksichtigung von Nicht-Index-Eigenschaften).

Bergi
quelle
9
for ... ofist in ES6 standardisiert.
Justin
2
Das ist seltsam, ich schwöre, ich habe irgendwo gelesen, dass es zurück auf ES7 verschoben wurde, aber anscheinend stimmte das nicht. Mein Fehler.
Alexander O'Mara
40
Eine Mnemonik: 'o'f -> not' o'bjects, 'i'n -> not' i'terables
Placoplatr
4
eine andere Mnemonik: for... of:: Arrays :: Arrays haben immer eine Länge, so dass Sie denken können for.. [n-te Element] of.. [q Elemente]
Nathan Smith
14
Eine weitere Mnemonik ... for..in..keys=== Fremdschlüssel === for...infür Schlüssel verwenden! Verwenden Sie daher for...offür Werte.
Gunther
237

Eine vollständige Antwort finde ich unter: https://www.typescriptlang.org/docs/handbook/iterators-and-generators.html (Obwohl es sich um ein Typenskript handelt, gilt dies auch für Javascript.)

Beide for..ofund for..inAnweisungen durchlaufen Listen. Die Werte, für die iteriert wird, sind jedoch unterschiedlich. for..inGibt eine Liste der Schlüssel für das zu iterierende Objekt zurück, während for..ofeine Liste der Werte der numerischen Eigenschaften des zu iterierenden Objekts zurückgegeben wird.

Hier ist ein Beispiel, das diese Unterscheidung demonstriert:

let list = [4, 5, 6];

for (let i in list) {
   console.log(i); // "0", "1", "2",
}

for (let i of list) {
   console.log(i); // "4", "5", "6"
}

Ein weiterer Unterschied ist, dass for..in auf jedes Objekt einwirkt; Es dient als Möglichkeit, Eigenschaften für dieses Objekt zu überprüfen. for..ofinteressiert sich dagegen hauptsächlich für Werte iterierbarer Objekte. Integrierte Objekte wie Map und Set implement Symbol.iteratorermöglichen den Zugriff auf gespeicherte Werte.

let pets = new Set(["Cat", "Dog", "Hamster"]);
pets["species"] = "mammals";

for (let pet in pets) {
   console.log(pet); // "species"
}

for (let pet of pets) {
    console.log(pet); // "Cat", "Dog", "Hamster"
}
Alireza Fattahi
quelle
1
Außerdem ruft man so etwas wie for auf (let i of {}) {console.log (i); } würde einen TypeError auslösen: VM391: 1 Nicht gefangener TypeError: {} ist nicht iterierbar bei <anonymous>: 1: 14, zumindest in Chrome
kboom
TS für den Sieg - das Beispiel ist falsch, letzteres sollte "Säugetiere" zurückgeben, nicht // "Katze", "Hund", "Hamster"
martinp999
8
Ich erinnere mich daran: für "in" für index. Und dann für "von" wäre das valuesvon jedem Index / Schlüssel / Gegenstand.
SherylHohman
Schön, dass dies für mich der König sein wird: Die Verwendung von For-Ins für die Iteration von Elementen, die ich normalerweise erstellen muss, um eine let thisItem = items[all];Variable zu erstellen , for...ofhilft dabei, dies zu verknüpfen!
Vasily Hall
Ich erinnere mich daran: for...inwie Object.keys(), weißt du was? Arrays sind Objekte, die auch ihre Unabhängigkeiten zurückgeben würden. :)
Sujeet Agrahari
38

Für ... in Schleife

Die for ... in- Schleife verbessert die Schwächen der for-Schleife, indem die Zähllogik und die Ausgangsbedingung beseitigt werden.

Beispiel:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

Sie müssen sich jedoch noch mit dem Problem befassen, einen Index zu verwenden, um auf die Werte des Arrays zuzugreifen, und das stinkt. es macht es fast verwirrender als zuvor.

Außerdem kann die for ... in-Schleife Sie in große Schwierigkeiten bringen, wenn Sie einem Array (oder einem anderen Objekt) eine zusätzliche Methode hinzufügen müssen. Da für ... in Schleifen alle aufzählbaren Eigenschaften durchlaufen, bedeutet dies, dass diese Eigenschaften auch in der Schleife angezeigt werden, wenn Sie dem Prototyp des Arrays zusätzliche Eigenschaften hinzufügen.

Array.prototype.decimalfy = function() {
  for (let i = 0; i < this.length; i++) {
    this[i] = this[i].toFixed(2);
  }
};

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const index in digits) {
  console.log(digits[index]);
}

Drucke:

0

1

2

3

4

5

6

7

8

9

function () {for (sei i = 0; i <this.length; i ++) {this [i] = this [i] .toFixed (2); }}

Aus diesem Grund wird davon abgeraten, for ... in-Schleifen beim Durchlaufen von Arrays zu verwenden.

HINWEIS : Die forEach-Schleife ist ein anderer Typ der for-Schleife in JavaScript. Da forEach()es sich jedoch tatsächlich um eine Array-Methode handelt, kann sie nur ausschließlich mit Arrays verwendet werden. Es gibt auch keine Möglichkeit, eine forEach-Schleife anzuhalten oder zu unterbrechen. Wenn Sie diese Art von Verhalten in Ihrer Schleife benötigen, müssen Sie eine grundlegende for-Schleife verwenden.

Für ... der Schleife

Die for ... of- Schleife wird verwendet, um alle Arten von Daten zu durchlaufen, die iterierbar sind.

Beispiel:

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  console.log(digit);
}

Drucke:

0

1

2

3

4

5

6

7

8

9

Dies macht die for ... of-Schleife zur prägnantesten Version aller for-Schleifen.

Aber warte, da ist noch mehr! Die for ... of-Schleife hat auch einige zusätzliche Vorteile, die die Schwächen der for und for ... in Schleifen beheben.

Sie können eine for ... -Schleife jederzeit stoppen oder unterbrechen.

const digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

for (const digit of digits) {
  if (digit % 2 === 0) {
    continue;
  }
  console.log(digit);
}

Drucke:

1

3

5

7

9

Und Sie müssen sich keine Gedanken über das Hinzufügen neuer Eigenschaften zu Objekten machen. Die for ... of-Schleife durchläuft nur die Werte im Objekt.

Elar
quelle
2
" Die for ... in-Schleife verbessert die Schwächen der for-Schleife, indem die Zähllogik und die Ausgangsbedingung beseitigt werden " - nein, das ist nicht das, was sie tut. Ganz und gar nicht.
Bergi
1
@Bergi Könnten Sie vielleicht klarstellen, warum Sie denken, dass dies nicht der Fall ist und was Ihrer Meinung nach tatsächlich verbessert wird?
Elar
2
Es verbessert nichts, es hat seine eigene Existenzberechtigung. Es macht etwas völlig anderes als eine for (var index=0; index<arr.length; index++)Schleife (wobei der indexZähler im Gegensatz zu Ihrem Beispiel eine ganze Zahl ist).
Bergi
Art macht es verwirrend, dass die Array-Werte, die Sie für das Beispiel ausgewählt haben, mit den Array-Indexwerten übereinstimmen ...
Sergey
20

Unterschied for..inund for..of:

Beide for..inund for..ofsind Schleifenkonstrukte, die zum Iterieren über Datenstrukturen verwendet werden. Der einzige Unterschied besteht darin, was sie wiederholen:

  1. for..initeriert über alle aufzählbaren Eigenschaftsschlüssel eines Objekts
  2. for..ofiteriert über die Werte eines iterierbaren Objekts. Beispiele für iterierbare Objekte sind Arrays, Strings und NodeLists.

Beispiel:

let arr = ['el1', 'el2', 'el3'];

arr.addedProp = 'arrProp';

// elKey are the property keys
for (let elKey in arr) {
  console.log(elKey);
}

// elValue are the property values
for (let elValue of arr) {
  console.log(elValue)
}

In diesem Beispiel können wir beobachten, dass die for..inSchleife über die Schlüssel des Objekts iteriert, das in diesem Beispiel ein Array-Objekt ist. Die Schlüssel sind 0, 1, 2, die den hinzugefügten Array-Elementen und entsprechen addedProp. So sieht das arrArray-Objekt in Chrome Devtools aus:

Geben Sie hier die Bildbeschreibung ein

Sie sehen, dass unsere for..inSchleife nichts weiter tut, als einfach über diese Werte zu iterieren.


Die for..ofSchleife in unserem Beispiel durchläuft die Werte einer Datenstruktur. Die Werte in diesem speziellen Beispiel sind 'el1', 'el2', 'el3'. Die Werte, die eine iterierbare Datenstruktur zurückgibt, for..ofhängen vom Typ des iterierbaren Objekts ab. Beispielsweise gibt ein Array die Werte aller Array-Elemente zurück, während eine Zeichenfolge jedes einzelne Zeichen der Zeichenfolge zurückgibt.

Willem van der Veen
quelle
8

Die for...inAnweisung durchläuft die aufzählbaren Eigenschaften eines Objekts in beliebiger Reihenfolge. Aufzählbare Eigenschaften sind jene Eigenschaften, deren internes [[Aufzählbar]] - Flag auf true gesetzt ist. Wenn also eine aufzählbare Eigenschaft in der Prototypkette vorhanden ist, wird die for...inSchleife auch diese durchlaufen.

Die for...ofAnweisung iteriert über Daten, über die das iterierbare Objekt definiert werden soll.

Beispiel:

Object.prototype.objCustom = function() {}; 
Array.prototype.arrCustom = function() {};

let iterable = [3, 5, 7];

for (let i in iterable) {
  console.log(i); // logs: 0, 1, 2, "arrCustom", "objCustom"
}

for (let i in iterable) {
  if (iterable.hasOwnProperty(i)) {
    console.log(i); // logs: 0, 1, 2,
  }
}

for (let i of iterable) {
  console.log(i); // logs: 3, 5, 7
}

Wie zuvor können Sie das Hinzufügen hasOwnPropertyvon for...ofSchleifen überspringen .

Ramandeep Sohi
quelle
7

Die for-in-Anweisung durchläuft die aufzählbaren Eigenschaften eines Objekts in beliebiger Reihenfolge.

Die Schleife durchläuft alle aufzählbaren Eigenschaften des Objekts selbst und die Eigenschaften, die das Objekt vom Prototyp seines Konstruktors erbt

Sie können sich vorstellen, dass "for in" im Grunde genommen alle Schlüssel iteriert und auflistet.

var str = 'abc';
var arrForOf = [];
var arrForIn = [];

for(value of str){
  arrForOf.push(value);
}

for(value in str){
  arrForIn.push(value);
}

console.log(arrForOf); 
// ["a", "b", "c"]
console.log(arrForIn); 
// ["0", "1", "2", "formatUnicorn", "truncate", "splitOnLast", "contains"]
Devdutta Natu
quelle
for in zeigt die Schlüssel nur an, wenn sie von uns hinzugefügt wurden, es wird nicht formatUnicorn
Milad
1
"formatUnicorn", "truncate", "splitOnLast", "enthält" Ausdruck, da der Stapelüberlauf überschrieben wird String.prototype.
Jasonxia23
6

Es gibt einige bereits definierte Datentypen, mit denen wir sie leicht durchlaufen können, z. B. Array-, Map- und String-Objekte

Normal für in Iterationen über den Iterator und als Antwort liefert uns die Schlüssel, die in der Reihenfolge der Einfügung sind, wie im folgenden Beispiel gezeigt.

  const numbers = [1,2,3,4,5];
   for(let number in number) {
     console.log(number);
   }

   // result: 0, 1, 2, 3, 4

Wenn wir nun dasselbe mit for of versuchen , liefert es uns als Antwort die Werte, nicht die Schlüssel. z.B

  const numbers = [1,2,3,4,5];
   for(let numbers of numbers) {
    console.log(number);
  }

  // result: 1, 2, 3, 4, 5

Wenn wir uns also beide Iteratoren ansehen, können wir den Unterschied zwischen beiden leicht unterscheiden.

Hinweis: - For of funktioniert nur mit dem Symbol.iterator

Wenn wir also versuchen, über ein normales Objekt zu iterieren, erhalten wir einen Fehler, z.

const Room = {
   area: 1000,
   height: 7,
   floor: 2
 }

for(let prop in Room) {
 console.log(prop);
 } 

// Result area, height, floor

for(let prop of Room) {
  console.log(prop);
 } 

Der Raum ist nicht iterierbar

Zum Durchlaufen müssen wir nun einen ES6 Symbol.iterator definieren, z

  const Room= {
    area: 1000, height: 7, floor: 2,
   [Symbol.iterator]: function* (){
    yield this.area;
    yield this.height;
    yield this.floors;
  }
}


for(let prop of Room) {
  console.log(prop);
 } 

//Result 1000, 7, 2

Dies ist der Unterschied zwischen For in und For of . Hoffe, dass es den Unterschied klären könnte.

Amit Mundra
quelle
5

Ein weiterer Unterschied zwischen den beiden Schleifen, den noch niemand erwähnt hat:

Die Destrukturierung for...inist veraltet. Verwenden Sie for...ofstattdessen.

Quelle

Wenn wir also die Destrukturierung in einer Schleife verwenden möchten , um sowohl den Index als auch den Wert jedes Array- Elements zu erhalten, sollten wir die for...ofSchleife mit der Array- Methode verwenden entries():

for (const [idx, el] of arr.entries()) {
    console.log( idx + ': ' + el );
}
simhumileco
quelle
1
Ja @GalMargalit, ich habe es sorgfältig gelesen. Ich bin damit einverstanden, dass das for each...inveraltet ist (erster Punkt), aber ich habe nicht darüber geschrieben ... Ich schrieb, dass "Destrukturierung for...inveraltet ist. Verwenden Sie for...ofstattdessen." (zweiter Punkt): developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Stimmen Sie mir zu @GalMargalit?
Simhumileco
1
Haha du hast recht, ich habe nicht sorgfältig gelesen! Es stimmt, ich habe im Grunde das Gleiche gedacht und dachte, Sie beziehen sich auf einen anderen.
Gal Margalit
2

Alle haben erklärt, warum dieses Problem auftritt, aber es ist immer noch sehr leicht, es zu vergessen und sich dann am Kopf zu kratzen, warum Sie falsche Ergebnisse erzielt haben. Besonders wenn Sie an großen Datenmengen arbeiten, wenn die Ergebnisse auf den ersten Blick in Ordnung zu sein scheinen.

Mit stellen Object.entriesSie sicher, dass Sie alle Eigenschaften durchlaufen:

var arr = [3, 5, 7];
arr.foo = "hello";

for ( var [key, val] of Object.entries( arr ) ) {
   console.log( val );
}

/* Result:

3
5
7
hello

*/
David C.
quelle
2

Ich sehe viele gute Antworten, aber ich entscheide mich, meine 5 Cent zu setzen, nur um ein gutes Beispiel zu haben:

Für in Schleife

iteriert über alle aufzählbaren Requisiten

let nodes = document.documentElement.childNodes;

for (var key in nodes) {
  console.log( key );
}

Für von Schleife

iteriert über alle iterierbaren Werte

let nodes = document.documentElement.childNodes;

for (var node of nodes) {
  console.log( node.toString() );
}

WebBrother
quelle
2

Als ich anfing, die for in- und of-Schleife zu lernen , war ich auch mit meiner Ausgabe verwirrt, aber mit ein paar Recherchen und Verständnis kann man sich die einzelne Schleife wie folgt vorstellen: Die

  1. for ... in loop gibt die Indizes der einzelnen Eigenschaft zurück und hat keine Auswirkungen auf den Wert der Eigenschaft . Sie schleift und gibt Informationen zur Eigenschaft und nicht zum Wert zurück . Z.B

let profile = { name : "Naphtali", age : 24, favCar : "Mustang", favDrink : "Baileys" }

Der obige Code erstellt nur ein Objekt namens " Profil" . Wir verwenden es für unsere beiden Beispiele . Seien Sie also nicht verwirrt, wenn Sie das Profilobjekt in einem Beispiel sehen. Sie müssen nur wissen, dass es erstellt wurde.

Lassen Sie uns nun die for ... in-Schleife unten verwenden

for(let myIndex in profile){
    console.log(`The index of my object property is ${myIndex}`)
}
 // Outputs : 
        The index of my object property is 0
        The index of my object property is 1
        The index of my object property is 2
        The index of my object property is 3

Der Grund für die Ausgabe ist nun, dass wir vier (4) Eigenschaften in unserem Profilobjekt haben und die Indizierung, wie wir alle wissen, bei 0 ... n beginnt. Daher erhalten wir den Index der Eigenschaften 0,1,2,3, da wir es sind Arbeiten mit der for..in Schleife.

  1. for ... of loop * kann entweder die Eigenschaft , den Wert oder beides zurückgeben. Schauen wir uns an, wie. In JavaScript können wir Objekte nicht wie in Arrays normal durchlaufen. Daher gibt es einige Elemente, mit denen wir von einem Objekt aus auf eine unserer Auswahlmöglichkeiten zugreifen können.

    • Object.keys ( Objektname-geht-hierher ) >>> Gibt die Schlüssel oder Eigenschaften eines Objekts zurück.

    • Object.values ( Objektname-geht-hierher ) >>> Gibt die Werte eines Objekts zurück.

    • Object.entries ( Objektname-geht-hierher ) >>> Gibt sowohl die Schlüssel als auch die Werte eines Objekts zurück.

Nachfolgend finden Sie Beispiele für ihre Verwendung. Achten Sie auf Object.entries () :

Step One: Convert the object to get either its key, value, or both.
Step Two: loop through.


// Getting the keys/property

   Step One: let myKeys = ***Object.keys(profile)***
   Step Two: for(let keys of myKeys){
             console.log(`The key of my object property is ${keys}`)
           }

// Getting the values of the property

    Step One: let myValues = ***Object.values(profile)***
    Step Two : for(let values of myValues){
                 console.log(`The value of my object property is ${values}`)
               }

Wenn Sie Object.entries () verwenden, müssen Sie zwei Einträge für das Objekt aufrufen, dh die Schlüssel und Werte. Sie können beide über einen der Einträge aufrufen. Beispiel unten.

Step One: Convert the object to entries, using ***Object.entries(object-name)***
Step Two: **Destructure** the ***entries object which carries the keys and values*** 
like so **[keys, values]**, by so doing, you have access to either or both content.


    // Getting the keys/property

       Step One: let myKeysEntry = ***Object.entries(profile)***
       Step Two: for(let [keys, values] of myKeysEntry){
                 console.log(`The key of my object property is ${keys}`)
               }

    // Getting the values of the property

        Step One: let myValuesEntry = ***Object.entries(profile)***
        Step Two : for(let [keys, values] of myValuesEntry){
                     console.log(`The value of my object property is ${values}`)
                   }

    // Getting both keys and values

        Step One: let myBothEntry = ***Object.entries(profile)***
        Step Two : for(let [keys, values] of myBothEntry){
                     console.log(`The keys of my object is ${keys} and its value 
is ${values}`)
                   }

Machen Sie Kommentare zu unklaren Teileabschnitten.

Naphtali Duniya
quelle
1

Die for-inSchleife

for-inMit loop werden aufzählbare Eigenschaften einer Sammlung in beliebiger Reihenfolge durchlaufen . Eine Sammlung ist ein Objekt vom Typ Container, dessen Elemente einen Index oder einen Schlüssel verwenden können.

var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];
var myString = "123";

console.log( myObject[ 'a' ], myArray[ 1 ], myString[ 2 ] );

for-inDie Schleife extrahiert die aufzählbaren Eigenschaften ( Schlüssel ) einer Sammlung auf einmal und durchläuft sie einzeln. Eine aufzählbare Eigenschaft ist die Eigenschaft einer Sammlung, die in einer for-inSchleife angezeigt werden kann.

Standardmäßig werden alle Eigenschaften eines Arrays und eines Objekts in einer for-inSchleife angezeigt . Wir können jedoch die Object.defineProperty- Methode verwenden, um die Eigenschaften einer Sammlung manuell zu konfigurieren.

var myObject = {a: 1, b: 2, c: 3};
var myArray = [1, 2, 3];

Object.defineProperty( myObject, 'd', { value: 4, enumerable: false } );
Object.defineProperty( myArray, 3, { value: 4, enumerable: false } );

for( var i in myObject ){ console.log( 'myObject:i =>', i ); }
for( var i in myArray ){ console.log( 'myArray:i  =>', i ); }

Im obigen Beispiel werden die Eigenschaft dvon myObjectund der Index 3von myArraynicht in einer for-inSchleife angezeigt, da sie mit konfiguriert sind enumerable: false.

Es gibt nur wenige Probleme mit for-inSchleifen. Im Fall von Arrays for-inberücksichtigt die Schleife auch das methodsHinzufügen des Arrays mithilfe der myArray.someMethod = fSyntax, myArray.lengthbleibt jedoch bestehen 4.

Die for-ofSchleife

Es ist ein Missverständnis, dass for-ofSchleifen die Werte einer Sammlung durchlaufen. for-ofSchleife iteriert über ein IterableObjekt. Eine iterable ist ein Objekt, auf dem die Methode mit dem Namen Symbol.iteratordirekt auf einem ihrer Prototypen steht.

Symbol.iteratorMethode sollte einen Iterator zurückgeben . Ein Iterator ist ein Objekt mit einer nextMethode. Diese Methode wird als return valueund doneproperties bezeichnet.

Wenn wir ein iterierbares Objekt mit einer for-ofSchleife iterieren , wird die Symbol.iteratorMethode aufgerufen, sobald ein Iteratorobjekt abgerufen wird. Für jede Iteration der for-ofSchleife wird die nextMethode dieses Iteratorobjekts aufgerufen, bis doneder next()Aufruf false zurückgibt. Der Wert, den die for-ofSchleife für jede Iteration empfängt, wenn die valueEigenschaft vom next()Aufruf zurückgegeben wird.

var myObject = { a: 1, b: 2, c: 3, d: 4 };

// make `myObject` iterable by adding `Symbol.iterator` function directlty on it
myObject[ Symbol.iterator ] = function(){
  console.log( `LOG: called 'Symbol.iterator' method` );
  var _myObject = this; // `this` points to `myObject`
  
  // return an iterator object
  return {
    keys: Object.keys( _myObject ), 
    current: 0,
    next: function() {
      console.log( `LOG: called 'next' method: index ${ this.current }` );
      
      if( this.current === this.keys.length ){
        return { done: true, value: null }; // Here, `value` is ignored by `for-of` loop
      } else {
        return { done: false, value: _myObject[ this.keys[ this.current++ ] ] };
      }
    }
  };
}

// use `for-of` loop on `myObject` iterable
for( let value of myObject ) {
  console.log( 'myObject: value => ', value );
}

Die for-ofSchleife ist neu in ES6, ebenso wie Iterable und Iterables . Der ArrayKonstruktortyp hat eine Symbol.iteratorMethode für seinen Prototyp. Der ObjectKonstruktor hat es leider nicht Object.keys(), Object.values()und Object.entries()Methoden geben eine iterable zurück ( Sie können console.dir(obj)Prototypmethoden überprüfen ). Der Vorteil der for-ofSchleife besteht darin, dass jedes Objekt iterierbar gemacht werden kann, auch Ihre benutzerdefinierten Objekte Dogund AnimalKlassen.

Die einfache Möglichkeit, ein Objekt iterierbar zu machen, besteht darin, ES6 Generator anstelle einer benutzerdefinierten Iterator-Implementierung zu implementieren.

Im Gegensatz dazu for-inkann for-ofloop in jeder Iteration warten, bis eine asynchrone Aufgabe abgeschlossen ist. Dies erreicht man mit awaitSchlüsselwort nach forAussage Dokumentation .

Eine weitere großartige Sache bei for-ofLoop ist die Unicode-Unterstützung. Gemäß den ES6-Spezifikationen werden Zeichenfolgen mit UTF-16-Codierung gespeichert. Daher kann jedes Zeichen entweder 16-bitoder annehmen 32-bit. Traditionell wurden Zeichenfolgen mit UCS-2-Codierung gespeichert, die Zeichen unterstützt, die nur innerhalb gespeichert werden können 16 bits.

Gibt daher String.lengthdie Anzahl der 16-bitBlöcke in einer Zeichenfolge zurück. Moderne Zeichen wie ein Emoji-Zeichen benötigen 32 Bit. Daher würde dieses Zeichen lengthvon 2 zurückkehren . Die for-inSchleife iteriert über 16-bitBlöcke und gibt das falsche zurück index. Die for-ofSchleife durchläuft jedoch das einzelne Zeichen basierend auf den UTF-16-Spezifikationen.

var emoji = "😊🤣";

console.log( 'emoji.length', emoji.length );

for( var index in emoji ){ console.log( 'for-in: emoji.character', emoji[index] ); }
for( var character of emoji ){ console.log( 'for-of: emoji.character', character ); }

Uday Hiwarale
quelle
0

Ich fand die folgende Erklärung von https://javascript.info/array sehr hilfreich:

Eine der ältesten Methoden zum Wechseln von Array-Elementen ist die for-Schleife über Indizes:

let arr = ["Apple", "Orange", "Pear"];

for (let i = 0; i < arr.length; i++) { alert( arr[i] ); } But for arrays there is another form of loop, for..of:

let fruits = ["Apple", "Orange", "Plum"];

// iterates over array elements for (let fruit of fruits) { alert( fruit ); } The for..of doesn’t give access to the number of the current element, just its value, but in most cases that’s enough. And it’s shorter.

Da Arrays Objekte sind, ist es technisch auch möglich, Folgendes zu verwenden:

let arr = ["Apple", "Orange", "Pear"];

for (let key in arr) { alert( arr[key] ); // Apple, Orange, Pear } But that’s actually a bad idea. There are potential problems with it:

Die Schleife für..in durchläuft alle Eigenschaften, nicht nur die numerischen.

Es gibt sogenannte "Array-ähnliche" Objekte im Browser und in anderen Umgebungen, die wie Arrays aussehen. Das heißt, sie haben Längen- und Indexeigenschaften, aber sie können auch andere nicht numerische Eigenschaften und Methoden haben, die wir normalerweise nicht benötigen. Die for..in-Schleife listet sie jedoch auf. Wenn wir also mit Array-ähnlichen Objekten arbeiten müssen, können diese „zusätzlichen“ Eigenschaften zu einem Problem werden.

Die for..in-Schleife ist für generische Objekte und nicht für Arrays optimiert und daher 10-100-mal langsamer. Natürlich ist es immer noch sehr schnell. Die Beschleunigung kann nur bei Engpässen von Bedeutung sein. Trotzdem sollten wir uns des Unterschieds bewusst sein.

Im Allgemeinen sollten wir for..in nicht für Arrays verwenden.

Albert Leung
quelle
0

Hier ist eine nützliche Mnemonik, um sich an den Unterschied zwischen for...inLoop und for...ofLoop zu erinnern .

"Index in, Objekt von"

for...in Loop=> iteriert über den Index im Array.

for...of Loop=> iteriert über das Objekt von Objekten.

bnieland
quelle