Die Generator Comprehensions Syntax ist nicht standardisiert und wurde mit Firefox 58 entfernt. Zukünftig sollte stattdessen Generatoren eingesetzt werden.
Die Generator Comprehensions Syntax war ein JavaScript Ausdruck welcher es erlaubt schnell einen neuen Generator auf Basis eines existierenden Iterable Objektes zu erstellen. Jedoch wurde diese aus dem Standard und der Firefox Implementierung entfernt. Sie soll nicht mehr eingesetzt werden!
Syntax
(for (x of iterable) x) (for (x of iterable) if (condition) x) (for (x of iterable) for (y of iterable) x + y)
Beschreibung
In der Generator Comprehension gibt es zwei erlaubte Arten von Komponenten:
Die for-of Iteration ist immer die erste Komponente. Mehrere for-of Iterationen oder if Statements sind erlaubt.
Ein signifikanter Nachteil von Array Comprehensions ist, dass diese ein völlig neues Array im Speicher erstellt wird. Wenn der Input für die Comprehension selbst ein kleines Array ist, ist der entstehende Overhead nicht signifikant — aber wenn der Input ein langes Array ist oder ein teurer (oder tatsächlich unendlicher) Generator ist, kann die Erstellung eines neuen Arrays problematisch werden.
Generatoren erlauben das nachträgliche Berechnen von Sequenzen, mit Elementen, die dann Berechnet werden, wenn sie benötigt werden. Generator Comprehensions sind syntaktisch fast identisch zu Array Comprehensions — sie benutzen runde Klammern statt eckigen Klammern — jedoch erstellen sie Generator statt eines Arrays, welcher dann ausgeführt werden kann, wenn es benötigt wird. Man kann diese Funktion als Kurzsyntax für das Erstellen von Generatoren sehen.
Angenommen man hat ein Iterator it welcher über eine große Sequenz von Integers iteriert. Wir wollen einen neuen Iterator erstellen, der über das Doppelte des Integers iteriert. Eine Array Comprehension würde ein volles Array im Speicher erstellen, welches die doppelten Werte enthält:
var doubles = [for (i in it) i * 2];
Auf der anderen Seite würde eine Generator Comprehension einen neuen Iterator erstellen, welcher die verdoppelten Werte erste dann erstellt, wenn sie benötigt werden:
var it2 = (for (i in it) i * 2); console.log(it2.next()); // The first value from it, doubled console.log(it2.next()); // The second value from it, doubled
Wenn eine Generator Comprehension als Argument einer Funktion eingesetzt wird, können durch die Funktionsaufrufsklammern die äußeren Klammern weggelassen werden:
var result = doSomething(for (i in it) i * 2);
Der signifikante Unterschied zwischen den beiden Beispiel ist beim Einsatz der Generator Comprehension, dass man nur einmal über die ganze Datenstruktur iterieren muss, während bei der Array Comprehension zweimal iteriert werden muss, beim Erstellen und beim eigentlichen Iterieren.
Beispiele
Einfache Generator Comprehensions
(for (i of [1, 2, 3]) i * i ); // generator function which yields 1, 4, and 9 [...(for (i of [1, 2, 3]) i * i )]; // [1, 4, 9] var abc = ['A', 'B', 'C']; (for (letters of abc) letters.toLowerCase()); // generator function which yields "a", "b", and "c"
Generator Comprehensions mit if Statement
var years = [1954, 1974, 1990, 2006, 2010, 2014]; (for (year of years) if (year > 2000) year); // generator function which yields 2006, 2010, and 2014 (for (year of years) if (year > 2000) if (year < 2010) year); // generator function which yields 2006, the same as below: (for (year of years) if (year > 2000 && year < 2010) year); // generator function which yields 2006
Generator Comprehensions verglichen mit Generatorfunktionen
Ein einfacher Weg um Generator Comprehension Syntax zu verstehen ist es sie mit Generatorfunktionen zu vergleichen.
Beispiel 1: Einfacher Generator:
var numbers = [1, 2, 3];
// Generator function
(function*() {
for (let i of numbers) {
yield i * i;
}
})();
// Generator comprehension
(for (i of numbers) i * i );
// Result: both return a generator which yields [1, 4, 9]
Beispiel 2: Einsatz von if in Generatoren.
var numbers = [1, 2, 3];
// Generator function
(function*() {
for (let i of numbers) {
if (i < 3) {
yield i * 1;
}
}
})();
// Generator comprehension
(for (i of numbers) if (i < 3) i);
// Result: both return a generator which yields [1, 2]
Spezifikationen
Generator Comprehensions waren initial in dem ECMAScript 2015 Entwurf, jedoch wurden sie in der Überarbeitung 27 (August 2014) entfernt. Für Spezifikationssemantik muss in früheren Überarbeitungen von ES2015 nachgeschaut werden.
Browserkompatibilität
| Desktop | Mobile | Server | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Generator comprehensions | Chrome Keine Unterstützung Nein | Edge Keine Unterstützung Nein | Firefox Keine Unterstützung 30 — 58 | IE Keine Unterstützung Nein | Opera Keine Unterstützung Nein | Safari Keine Unterstützung Nein | WebView Android Keine Unterstützung Nein | Chrome Android Keine Unterstützung Nein | Firefox Android Keine Unterstützung 30 — 58 | Opera Android Keine Unterstützung Nein | Safari iOS Keine Unterstützung Nein | Samsung Internet Android Keine Unterstützung Nein | nodejs Keine Unterstützung Nein |
Legende
- Keine Unterstützung
- Keine Unterstützung
- Nicht standardisiert. Erwarte schlechte browserübergreifende Unterstützung.
- Nicht standardisiert. Erwarte schlechte browserübergreifende Unterstützung.
- Veraltet. Nicht für den Einsatz in neuen Webseiten gedacht.
- Veraltet. Nicht für den Einsatz in neuen Webseiten gedacht.
Unterschiede zu den älteren JS1.7/JS1.8 Comprehensions
Alte Comprehensions Syntax (nicht mehr benutzen!):
(X for (Y in Z)) (X for each (Y in Z)) (X for (Y of Z))
Unterschiede:
- ES7 Comprehensions erstellen einen Gültigkeitsbereich pro "for" Statement statt einen für die komplette Comprehension.
- Alt:
[...(()=>x for (x of [0, 1, 2]))][1]() // 2 - Neu:
[...(for (x of [0, 1, 2]) ()=>x)][1]() // 1, jede Iteration erstellt eine frische Bindung zu x.
- Alt:
- ES7 Comprehensions beginnen mit "for" statt eines Zuweisungsausdrucks.
- Alt:
(i * 2 for (i of numbers)) - Neu:
(for (i of numbers) i * 2)
- Alt:
- ES7 Comprehensions können mehrere
ifundforKomponenten haben. - ES7 Comprehensions funktionieren nur mit
und nicht mitfor...ofIteration.for...in