JavaScript Iterables

Das Protokoll der Iterationen ermöglicht es JavaScript Objekten, ihr Iterationsverhalten zu definieren und anzupassen, wie welche Werte in for...of geloopt werden.

Arrays gelten als iterierbar, aber es gibt auch andere Iterables (zum Beispiel Strings).

Beschreibung von Symbol.iterator

Versuchen wir, ein Iterable zu erstellen.

Es gibt zum Beispiel ein Objekt, das kein Array ist, aber für for...of geeignet sein kann.

Schauen wir uns ein Beispiel für ein Range-Objekt an, das einen Intervall von Zahlen darstellt:

let range = {
  from: 0,
  to: 10
}; 
// We want the for..of to work:
// for(let num of range) ... num=0,1,2,3,4,5,6,7,8,9,10

Um den Bereich in ein Iterable umzuwandeln, muss dem Objekt eine Methode hinzugefügt werden, die Symbol.iterator genannt wird.

Dies sind die Schritte:

  1. Sobald for..of beginnt, wird die Methode einmal aufgerufen. Sie sollte einen Iterator zurückgeben.
  2. Dann kann for..of mit dem zurückgegebenen Objekt arbeiten.
  3. Wenn for..of den nächsten Wert erwartet, wird next() auf diesem Objekt aufgerufen.
  4. Das Ergebnis sollte die Form {done: Boolean, value: any} enthalten.

Die volle Leistung für die Range mit Anmerkungen sieht folgendermaßen aus:

Javascript range object call Symbol.iterator
let range = { from: 0, to: 5 }; // 1. called to for..of initially calls this range[Symbol.iterator] = function () { //returns an iterator object: // 2.for..of works only with this iterator, querying it for next values return { currentValue: this.from, lastValue: this.to, // 3. next() is called at each iteration with a for..of loop next() { // 4. it should return the value as an object {done:.., value :...} if (this.currentValue <= this.lastValue) { return { done: false, value: this.currentValue++ }; } else { return { done: true }; } } }; }; for (let num of range) { console.log(num); // 0, then 1, 2, 3, 4, 5 }

Das wesentlichste Merkmal von Iterables ist die Trennung der Zuständigkeiten. Es betrachtet, dass das Iterator-Objekt von den Objekten, über die es iteriert, getrennt ist. Es ist möglich, sie mithilfe der Range wie einen Iterator zu verschmelzen, um den Code zu vereinfachen, wie im Folgenden gezeigt:

Javascript range object call Symbol.iterator
let range = { from: 0, to: 5, [Symbol.iterator]() { this.currentValue = this.from; return this; }, next() { if (this.currentValue <= this.to) { return { done: false, value: this.currentValue++ }; } else { return { done: true }; } } }; for (let num of range) { console.log(num); // 0, then 1, 2, 3, 4, 5 }

Der Hauptnachteil in diesem Fall ist, dass es nicht möglich ist, zwei for..of , die gleichzeitig über das Objekt laufen, zu haben.

Es können auch unendliche Iteratoren existieren. Zum Beispiel kann man die Range unendlich machen mit range.to = Infinity. Es gibt auch eine alternative Option: Man kann ein iterierbares Objekt erstellen, das eine unendliche Sequenz von pseudorandom Zahlen erzeugt. Daher gibt es keine Einschränkungen bei next, es kann noch mehr Werte zurückgeben. Daher wird auch die for..of Schleife bei einem iterable wie diesem endlos. Sie kann aber mit break gestoppt werden.

Strings als Iterables

Die am häufigsten verwendeten Iterables sind Strings und Arrays.

Die for..of kann über seine Zeichen loop bei einem String:

Javascript strings iterables
for (let char of "W3Docs") { // triggers 6 times: once for each character console.log(char); // W, then 3, then D, then o, then c, then s }

Es wird korrekt funktionieren, so:

Javascript strings iterables
let str = 'ȬẂ'; for (let char of str) { console.log(char); // Ȭ, and then Ẃ }

Array-ähnlich und Iterables

In diesem Abschnitt betrachten wir die Begriffe Iterables und Array-ähnlich. Sie mögen ähnlich erscheinen, sind aber sehr unterschiedlich.

Array-ähnlich gelten Objekte, die Indizes und length enthalten. Iterables sind Objekte, die in der Lage sind, die Methode Symbol.iterator zu implementieren. Diese Methode wurde oben beschrieben.

Beim Arbeiten mit JavaScript treffen Sie oft auf Array-ähnliche und iterable Objekte. Zum Beispiel können Strings sowohl Iterables als auch Array-ähnlich sein. Im Gegensatz dazu kann ein Iterable nie ein Array-ähnlich werden, und umgekehrt.

Lassen Sie uns ein Beispiel für ein Objekt anschauen, das Array-ähnlich, aber nicht iterierbar ist:

Javascript object is an array-like not an iterable
let arrLike = { // has indexes and length => array-like 0: "Welcome", 1: "to", 2: "W3Docs", length: 3 }; // Error (no Symbol.iterator) for (let item of arrLike) { console.log(item); }

In der Regel sind weder Iterables noch Array-ähnlich Arrays, da sie nicht die Methoden pop, push usw. enthalten.

Beschreibung des Array-Form

Das Array-Form ist eine allgemeine Methode, die verwendet wird, um ein iterable oder array-ähnlichen Wert zu nehmen und ein richtiges Array daraus zu machen. Danach können Array-Methoden darauf aufgerufen werden. Hier ist ein Beispiel für die Verwendung von Array-Form:

Javascript object is an array-like iterable
let arrLike = { 0: "Welcome", 1: "to", 2: "W3Docs", length: 3 }; let arr = Array.from(arrLike); // (*) console.log(arr.pop()); // W3Docs (method operates)

An der (*) Linie, akzeptiert Array.from das Objekt, prüft, ob es ein Array-ähnlichen oder ein Iterable ist, und erstellt ein neues Array, in das alle Elemente kopiert werden. Sehen wir uns an, wie das Gleiche mit einem Iterable passiert:

Javascript array an iterable
let range = { from: 0, to: 5, [Symbol.iterator]() { this.currentValue = this.from; return this; }, next() { if (this.currentValue <= this.to) { return { done: false, value: this.currentValue++ }; } else { return { done: true }; } } }; //confirming that the range is obtained from the above example let arr = Array.from(range); console.log(arr); // 0,1,2,3,4,5 ;array toString conversion works

Die volle Syntax von Array.from sieht so aus:

Array.from(obj[, mapFunc, thisArg])

Das zweite Argument mapFn ist eine Funktion, die vor dem Hinzufügen zu dem Array auf jedes Element angewendet werden kann. Das dritte Argument thisArg ermöglicht die Einstellung von this dafür. Hier ist ein Beispiel:

Javascript object is an array-like not an iterable
let range = { from: 0, to: 5, [Symbol.iterator]() { this.currentValue = this.from; return this; }, next() { if (this.currentValue <= this.to) { return { done: false, value: this.currentValue++ }; } else { return { done: true }; } } }; // provided that the range is taken from the above example // square of each number let arr = Array.from(range, num => num * num); console.log(arr); // 0,1,4,9,16,25

Nun, verwandeln wir einen String mit Hilfe von Array.from in ein Array von Zeichen:

Javascript turn a string into an array of characters
let str = 'ȬẂ'; // splits the str into an array of characters let chars = Array.from(str); console.log(chars[0]); // Ȭ console.log(chars[1]); // Ẃ console.log(chars.length); // 2

Im Gegensatz zur Methode str.split hängt sie von der iterierbaren Natur des Strings ab.

Es verhält sich genauso wie:

Javascript turn a string into an array of characters
let str = 'ȬẂ'; let charsArr = []; // Array.from internally does the same loop for (let char of str) { charsArr.push(char); } console.log(charsArr);

Zusammenfassung

Iterables sind Objekte, die in der for..of verwendet werden können.

In der Regel sollten sie die Methode Symbol.iterator ausführen. Diese Methode wird in der Regel automatisch von for..of aufgerufen. Es kann aber auch direkt erfolgen. Objekte, die indizierte Eigenschaften und length enthalten, gelten als array-ähnlich. Sie können auch andere Eigenschaften und Methoden enthalten, aber sie sind keine echten Arrays. Um sie in Arrays zu verwandeln, können Sie die Methode Array.from(obj[, mapFn, thisArg]) verwenden.

Die Arguments mapFn und thisArg ermöglichen es, eine Funktion auf jedes davon anzuwenden.

Quizzeit: Testen Sie Ihre Fähigkeiten!

Sind Sie bereit, das Gelernte herauszufordern? Tauchen Sie ein in unsere interaktiven Quizze für ein tieferes Verständnis und eine unterhaltsame Art, Ihr Wissen zu festigen.

Finden Sie das nützlich?