Generator Comprehensions

This is an archived page. It's not actively maintained.

Non standardisiert. Nicht einsetzen!
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

No compatibility data found. Please contribute data for "javascript.operators.generator_comprehensions" (depth: 1) to the MDN compatibility data repository.

Unterschiede zu den ├Ąlteren JS1.7/JS1.8 Comprehensions

JS1.7/JS1.8 Comprehensions wurden von Gecko 46 entfernt (Bug 1220564).

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.
  • ES7 Comprehensions beginnen mit "for" statt eines Zuweisungsausdrucks.
    • Alt: (i * 2 for (i of numbers))
    • Neu: (for (i of numbers) i * 2)
  • ES7 Comprehensions k├Ânnen mehrere if und for Komponenten haben.
  • ES7 Comprehensions funktionieren nur mit for...of und nicht mit for...in Iteration.

Siehe auch