Neu in JavaScript 1.7

  • Adressname der Version: JavaScript/Neu_in_JavaScript/1.7
  • Titel der Version: Neu in JavaScript 1.7
  • ID der Version: 451543
  • Erstellt:
  • Autor: eminor
  • Aktuelle Version? Nein
  • Kommentar

Inhalt der Version

{{ Fx_minversion_header(2) }}

JavaScript 1.7 ist ein Update für die Sprache, womit mehrere neue Features wie Generatoren, Iteratoren, Array-Comprehensions, let-Ausdrücke, und destructing assignments hinzugefügt wurden. Es enthält außerdem alle Features von JavaScript 1.6.

Die Unterstützung von JavaScript 1.7 beginnt mit Firefox 2.

Die in diesem Artikel enthaltenen Code-Beispiele können in der JavaScript-Shell getestet werden. Lesen Sie Introduction to the JavaScript shell, um mehr über die Benutzung der Shell zu lernen.

Verwendung von JavaScript 1.7

Möchte man einige der neuen Features von JavaScript 1.7 verwenden, sollte man dies angeben. Bei HTML oder XUL z. B. wie folgt:

<script type="application/javascript;version=1.7"></script>

Bei der Verwendung der JavaScript-Shell gibt man die Version über den Parameter -version 170 auf der Kommandozeile an oder benutzt die Funktion version():

version(170);

Neue Features bei denen die neuen Schüsselwörtern wie yield und let zum Einsatz kommen, setzen die Versionsangabe voraus, da bei existierendem Code diese Schlüsselwörter eventuell bereits als Bezeichner für Variablen oder Funktionen verwendet werden. Solche Features, die keine neuen Schlüsselwörter einführen (destructing assignments und Array-Comprehensions) können ohne die Versionsangabe verwendet werden.

Generatoren und Iteratoren (siehe Iteratoren und Generatoren)

Bei der Entwicklung von Code, in dem iterative Algorithmen eingesetzt werden (wie z. B. Iterieren über Listen, XML-Nodes, Datenbank-Ausgaben; oder wiederholtes Verarbeiten desselben Datensatzes) gibt es oft Status-Variablen, deren Werte während des Verbeitungsprozesses verändert werden müssen. Tradiotionell müssen die vorübergehenden Werte dann über eine Callback-Funktion bezogen werden.

Generatoren

Hier ein Beispiel mit einem iterativer Algorithmus für die Berechnung von Fibonacci-Zahlen:

function do_callback(num) {
  console.log(num);
}

function fib() {
  var i = 0, j = 1, n = 0;
  while (n < 10) {
    do_callback(i);
    var t = i;
    i = j;
    j += t;
    n++;
  }
}

fib();

Bei diesem Code kommt eine Callback-Routine zum Einsatz, um bei jedem iterativen Schritt des Algorithmus bestimmte Operationen durchzuführen. In diesem Fall wird jede Fibonacci-Zahl einfach auf der Konsole ausgegeben.

Generatoren und Iteratoren arbeiten zusammen, um dies besser umzusetzen. Im Anschluss ein Beispiel zur Berechnung von Fibonacci-Zahlen unter Einsatz eines Generators:

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i < 10; i++) {
  console.log(g.next());
}

Bei der Funktion, welche das Schlüsselwort yield enthält, handelt es sich um einen Generator. Beim Aufruf dieser Funktion werden ihre formalen Parameter an aktuelle Argumente gebunden, aber der Code nicht ausgeführt, sondern stattdessen ein Generator-Iterator zurückgegeben. Bei jedem Aufruf der next()-Methode des Generator-Iterators wird dann ein weiterer Iterationsschritt ausgeführt. Der Rückgabewert jedes Durchlaufs ist der nach yield stehende Wert. Man kann sich yield ungefähr wie eine spezielles return für Generator-Iterator-Objekte vorstellen, welches die Begrenzung für jeden Iterationsschritt festlegt. Bei jedem Aufruf von next() wird die Ausführung dann bei der Anweisung nach yield fortgesetzt.

Ein Generator-Iterator wird durchlaufen, indem die Methode next() wiederholt aufgerufen wird, solange bis schließlich das gewünscht Ergebnis erreicht bzw. die Bedingung erfüllt ist. Bei dem Beispiel mit den Fibonacci-Zahlen wird also wiederholt g.next() aufgerufen, bis man die gewünschte Anzahl von Fibonacci-Zahlen erzeugt hat.

Fortsetzen eines Generators an einem bestimmten Punkt

Sobald ein Generator einmal durch den Aufruf der next()-Methode gestartet wurde, kann über die Methode send() ein beliebiger Wert an den Generator übergeben werden. Dieser Wert wird dann so interpriert, als wäre es der Wert des letzten yield. Der Generator gibt dann den Operanden des darauf folgenden yield zurück.

Ein Generator lässt sich nicht direkt an einem bestimmten Punkt starten, sondern nur über die Methode next(). Erst nach dem next()-Aufruf kann über send() ein Wert gesetzt werden.

Achtung: Der Aufruf von send(undefined) ist äquivalent zum Aufruf von next(). Jeder Start eines neuen Generator über send() mit einem anderen Wert als undefined resultiert jedoch in einem TypeError-Ausnahmefehler.

Ausnahmen bei Generatoren

Man kann einen Generator dazu bringen, eine Ausnahme auszuwerfen, indem man seine throw()-Methode aufruft und ihr den Wert übergibt, der ausgeworfen werden soll. Diese Ausnahme wird unter Einbeziehung des Kontext des aktuellen Unterbrechung ausgeworfen, so als wäre das yield des aktuellen Durchlaufs eine Anweisung throw Wert.

Trifft die Ausführung während der Verarbeitung der ausgeworfenen Ausnahme auf kein yield, so verbreitet sich die Ausnahme bis nach oben durch den Aufruf bis zu next() und nachfolgende Aufrufe von next() lösen eine StopIteration-Ausnahme aus.

Schließen eines Generators

Generatoren besitzen eine Methode close(), welche den Generator zwingt, sich selbst zu schließen. Eine solchen Schließung wirkt sich wie folgt aus:

  1. Jede finally-Klausel, die in der Generator-Funktion aktiv ist, wird ausgeführt.
  2. Wird durch eine finally-Klausel eine andere Ausnahme als StopIteration ausgeworfen, so wird diese an die Funktion weitergeleitet, die close() aufgerufen hat.
  3. Der Generator terminiert.

Generator-Beispiel

Dieser Code arbeitet mit einem Generator, der alle 100 Schleifendurchläufe etwas "abwirft" (yield = abwerfen):

var gen = generator();

function driveGenerator() {
  if (gen.next()) {
    window.setTimeout(driveGenerator, 0);	
  } else {
    gen.close();	
  }
}

function generator() {
  while (i < something) {
    /** stuff **/

    ++i;
    /** 100 loops per yield **/
    if ((i % 100) == 0) {
      yield true;
    } 
  }
  yield false;
}

Iteratoren

Ein Iterator ist ein spezielles Objekt, das es erlaubt über Daten zu iterieren.

Bei der normalen Benutzung sind Iterator-Objekte "unsichtbar"; man braucht sie nicht explizit abzusprechen, sondern setzt stattdessen for...in und for each...in Anweisungen ein, um über Schlüssel und/oder Werte von Objekten zu iterieren.

var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  console.log(objectWithIterator[i]);
}

Für die Implementierung eines eigenen Iterator-Objekts oder zur direkten Manipulation von Iteratoren sollte man über die next()-Methode, die StopIteration-Ausnahme und die __iterator__-Methode informiert sein.

Ein Iterator für ein Objekt kann man mit dem Aufruf von Iterator(objectname); erzeugen. Der Iterator kann über die Methode __iterator__ gefunden werden; ist diese Methode nicht vorhanden, handelt es sich um einen Default-Iterator. Ein Default-Iterator wirft über yield die Eigenschaften des Objekts ab. Möchte man stattdessen einen selbstdefinierten Iterator einsetzen, überschreibt man die Methode __iterator__, damit diese eine Instanz des selbstbefinierten Iterators zurückgibt. Um den Iterator eines Objekts über ein Skript abzufragen, sollte man auf Iterator(obj) statt direkt auf __iterator__ zurückgreifen. Ersteres funktioniert für Arrays, letzteres nicht.

Nach Erzeugung des Iterators kann man einfach über die Methode next() das nächste Element abfragen. Sind keine Daten mehr vorhanden, wird eine StopIteration-Ausnahme ausgeworfen.

Hier ein einfaches Beispiel für die direkte Manipulation eines Iterators:

var obj = {name:"Jack Bauer", username:"JackB", id:12345, agency:"CTU",
          region:"Los Angeles"};

var it = Iterator(obj);

try {
  while (true) {
    print(it.next() + "\n");
  }
} catch (err if err instanceof StopIteration) {
  print("End of record.\n");
} catch (err) {
  print("Unknown error: " + err.description + "\n");
}

Die Ausgabe dieses Codes ist wie folgt:

name,Jack Bauer
username,JackB
id,12345
agency,CTU
region,Los Angeles
End of record.

Optional kann man bei der Erstellung eines Iterators einen booleschen Wert als zweiten Parameter angeben, womit festgelegt wird, ob nur der jeweilge Schlüssel beim Aufruf der next()-Methode zurückgegeben werden soll. Kommt eine benutzerdefinierte __iterator__-Funktionen zum Einsatz, wird der Wert als einziges Argument an diese übergeben. Würde man beim Beispiel oben die Anweisung var it = Iterator(obj); in var it = Iterator(obj, true); ändern, würde man folgende Ausgabe erhalten:

name
username
id
agency
region
End of record.

In beiden Fällen kann die Reihenfolge der Datenausgabe - je nach Implemetierung - variieren. Es gibt keine Garantie für eine bestimmte Anordung der ausgegebenen Daten.

Iteroren sind nützlich, um die Daten in einem Objekt abzufragen. Solche Objekte, die Daten enthalten, von denen man zunächst nicht weiß, eingeschlossen. Das kann hilfreich sein, wenn man Daten hinterlegen muss, die von einer Applikation nicht erwartet werden.

Array-Comprehensions (siehe Array comprehensions)

Array-Comprehensions nutzen Generatoren für die effiziente Initialisierung von Arrays. Zum Beispiel:

function range(begin, end) {
  for (let i = begin; i < end; ++i) {
    yield i;
  }
}

range() ist ein Generator, der alle Werte zwischen begin und end zurückgibt. Nach der Definition kann der Generator wie folgt benutzt werden:

var ten_squares = [i * i for each (i in range(0, 10))];

Damit wird ein Array ten_squares vorinitialisiert, welches die Qudratzahlen der Werte von 0 bis 9 enthält.

Bei der Initialisierung können beliebige Bedingungen angegeben werden. Mit folgendem Code wird z. B. ein Array initialisiert, welches die geraden Zahlen zwischen 0 und 20 enthält:

var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];

Bei Versionen vor JavaScript 1.7 würde man dies ungefähr so umsetzen:

var evens = [];
for (var i=0; i <= 20; i++) {
  if (i % 2 == 0)
    evens.push(i);
}

Die Array-Comprehension ist nicht nur kompakter, sondern auch lesbarer, sobald man das Konzept einmal verstanden hat.

Regeln für die Sichtbarkeit (Scope)

Array-Comprehensions sind von einen impliziten Block abgegrenzt, der alles, was zwischen den eckige Klammern steht, einschließt; inklusive impliziter let-Deklarationen.

Block-Begrenzungen mit let (siehe let Statement)

Es gibt verschiedene Möglichkeiten, wie mit let Blockbegrenzungen von Daten und Funktionen verwaltet werden können.

  • Die let-Anweisung ermöglicht die Zuweisung von Werten an Variable innerhalb des Sichtbarkeitsbereichs eines Blocks, ohne dass Werten gleichnamiger Variablen außerhalb dieses Blocks beeinflusst werden.
  • Mit dem let-Ausdruck können Variablen erzeugt werden, die nur für einen einzelnen Ausdruck gelten. 
  • Die let-Definition definiert Variablen, dessen Sichtbarkeitsbereich durch den Block in dem sie definiert wurden, bestimmt wird. Diese Syntax ist der von var sehr ähnlich.
  • Außerdem können mit let  Variablen erzeugt werden, die nur innerhalb des Kontext einer for-Schleife sichtbar sind.

let-Anweisung

Die let-Anweisung ermöglicht die Erzeugung eines lokalen Sichtbarkeitsbereichs für Variablen. Eine oder mehrere Variablen werden an die lexikalische Begrenzung eines einzelnen Blocks gebunden. Andernfalls ist es exakt das Gleiche wie eine Block-Anweisung. Der Sichtbarkeitsbereich einer mit var deklarierten Variablen ist allerdings - auch wenn sie innerhalb der let-Anweisung deklariert wurde - noch immer der Sichtbarkeitsbreich der Funktion. Mit var deklarierten Variablen verhalten sich also exakt gleich, wenn sie innerhalb oder außerhalb der let-Anweisung deklariert werden - sie befinden sich im Sichtbarkeitsbereich der Funktion.

Zum Beispiel:

var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

console.log(x + y); // 5

Die Regeln für den Code-Block sind dieselben wie bei jedem anderen Block bei JavaScript. Mit Hilfe der let-Declarationen könnten eigene lokale Variablen bestimmt werden.

Achtung: Bei der Syntax für  let-Anweisungen sind die Klammern nach let nicht optional, sondern müssen unbedingt angegeben werden; das Weglassen der Klammern resultiert in einem Syntaxfehler.

Regeln für den Sichtbarkeitsbereich (Scope)

Der Sichtbarkeitsbereich von Variablen, die mit let deklariert werden, ist der let-Block selbst, Blöcke innerhalb dieses Blocks eingeschlossen - solange sie Variablen mit den gleichen Namen definieren.

let-Ausdrücke

Mit let kann die Sichtbarkeit von Variablen auf einzelne Ausdrücke beschränkt werden:

var x = 5;
var y = 0;
console.log(let(x = x + 10, y = 12) x + y);
console.log(x + y);

Ausgabe:

27
5

In diese Fall ist der Sichtbarkeitsbereich für die Variablen x und y bei den Zuweisungen der Werte x+10 und 12 auf den Ausdruck x + y + "<br>\n" beschränkt.

Regeln für die Sichtarkeit (Scope)

Gegeben ist ein let-Ausdruck:

let (decls) expr

Dann wird um expr herum ein impliziter Block erzeugt.

let-Definitionen

Das Schlüsselwort let kann auch für die Definition von Variablen in einem Block verwendet werden.

Achtung: Falls Ihnen mehr interessante Beispiele einfallen, fügen Sie diese bitte hinzu.
if (x > y) {
  let gamma = 12.7 + y;
  i = gamma * x;
}

You can use let definitions to alias pseudo-namespaced code in extensions. (See Security best practices in extensions.)

let Cc = Components.classes, Ci = Components.interfaces;

let-Anweisungen, -Ausdrücke und -Definitionen sorgen manchmal für saubereren Code, wenn innere Funktionen benutzt werden:

var list = document.getElementById("list");

for (var i = 1; i <= 5; i++) {
  var item = document.createElement("LI");
  item.appendChild(document.createTextNode("Item " + i));

  let j = i;
  item.onclick = function (ev) {
    alert("Item " + j + " is clicked.");
  };
  list.appendChild(item);
}

Der Code funktioniert wie erwartet, da die fünf Instanzen der (anonymen) inneren Funktion mit fünf unterschiedlichen Instanzen der Variablen j arbeiten. Der Code würde so nicht funktionieren, wenn man var statt let verwenden oder die Variable j entfernen und einfach die Variable i in der inneren Funktion benutzen würde.

Regeln für den Sichtbarkeitsbereich (Scope)

Durch let deklarierte Variablen sind in dem Block in dem sie definiert wurden sichtbar, als auch in jedem inneren Block, sofern sie darin nicht neu definiert wurden. Hier verhält sich let also sehr ähnlich wie var. Der größte Unterschied besteht darin, dass bei var-Variablen der Sichtbarkeitsbereich die ganze einschließende Funktion ist:

function varTest() {
  var x = 31;
  if (true) {
    var x = 71;  // dieselbe Variable!
    alert(x);  // 71
  }
  alert(x);  // 71
}

function letTest() {
  let x = 31;
  if (true) {
    let x = 71;  // andere Variable!
    alert(x);  // 71
  }
  alert(x);  // 31
}

Der Ausdruck auf der rechten Seite des Gleichzeichens ist innerhalb des Blocks, anders als bei let-Ausdrücken und let-Anweisungen:

function letTests() {
  let x = 10;

  // let-Anweisung
  let (x = x + 20) {
    alert(x);  // 30
  }

  // let-Ausdruck
  alert(let (x = x + 20) x);  // 30

  // let-Definition
  {
    let x = x + 20;  // x here evaluates to undefined
    alert(x);  // undefined + 20 ==> NaN
  }
}

Beim Top-Level von Skripten und Funktionen verhält sich let exakt wie var. Zum Beispiel:

var x = 'global';
let y = 'global';
console.log(this.x);
console.log(this.y);

Die Ausgabe ist hier zweimal "global".

Achtung: Die globalen Sichtbarkeitsregeln von let-Definitionen ändern sich voraussichtlich bei ES6.

let-Variablen in for-Schleifen

Mit Hilfe von let können Variablen lokal an den Sichtbarkeitsbereich einer for-Schleife gebunden werden. Im Kopf der Schleife definierte var-Variablen sind hingegen innerhalb der ganzen Funktion sichtbar.

var i=0;
for ( let i=i ; i < 10 ; i++ )
  console.log(i);

for ( let [name,value] in Iterator(obj) )
  console.log("Name: " + name + ", Value: " + value);

Scoping rules

for (let expr1; expr2; expr3) statement

In this example, expr2, expr3, and statement are enclosed in an implicit block that contains the block local variables declared by let expr1. This is demonstrated in the first loop above.

for (let expr1 in expr2) statement
for each(let expr1 in expr2) statement

In both these cases, there are implicit blocks containing each statement. The first of these is shown in the second loop above.

Destructuring assignment (Merge into own page/section)

Destructuring assignment makes it possible to extract data from arrays or objects using a syntax that mirrors the construction of array and object literals.

The object and array literal expressions provide an easy way to create ad-hoc packages of data. Once you've created these packages of data, you can use them any way you want to. You can even return them from functions.

One particularly useful thing you can do with destructuring assignment is to read an entire structure in a single statement, although there are a number of interesting things you can do with them, as shown in the section full of examples that follows.

This capability is similar to features present in languages such as Perl and Python.

Examples

Destructuring assignment is best explained through the use of examples, so here are a few for you to read over and learn from.

Avoiding temporary variables

You can use destructuring assignment, for example, to swap values:

var a = 1;
var b = 3;

[a, b] = [b, a];

After executing this code, b is 1 and a is 3. Without destructuring assignment, swapping two values requires a temporary variable (or, in some low-level languages, the XOR-swap trick).

Similarly, it can be used to rotate three or more variables:

var a = 'o', 
    b = "<span style='color:green;'>o</span>", 
    c = 'o', 
    d = 'o', 
    e = 'o', 
    f = "<span style='color:blue;'>o</span>", 
    g = 'o',
    h = 'o';

for ( var lp=0; lp < 40; lp++ ) {

  [a, b, c, d, e, f, g, h] = [b, c, d, e, f, g, h, a];

  document.write(a+''+b+''+c+''+d+''+e+''+f+''+g+''+h+''+"<br />");

}

After executing this code, a visual colorful display of the variable rotation will be displayed.

Returning to our Fibonacci generator example from above, we can eliminate the temporary "t" variable by computing the new values of "i" and "j" in a single group-assignment statement:

function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    [i, j] = [j, i + j];
  }
}

var g = fib();
for (let i = 0; i < 10; i++)
  print(g.next());

Multiple-value returns

Thanks to destructuring assignment, functions can return multiple values. While it's always been possible to return an array from a function, this provides an added degree of flexibility.

function f() {
  return [1, 2];
}

As you can see, returning results is done using an array-like notation, with all the values to return enclosed in brackets. You can return any number of results in this way. In this example, f() returns the values {{ mediawiki.external('1, 2') }} as its output.

var a, b;
[a, b] = f();
console.log("A is " + a + " B is " + b);

The statement {{ mediawiki.external('a, b') }} = f() assigns the results of the function to the variables in brackets, in order: a is set to 1 and b is set to 2.

You can also retrieve the return values as an array:

var a = f();
console.log("A is " + a);

In this case, a is an array containing the values 1 and 2.

Looping across objects

You can also use destructuring assignment to pull data out of an object:

let obj = { width: 3, length: 1.5, color: "orange" };

for (let [name, value] in Iterator(obj)) {
  console.log("Name: " + name + ", Value: " + value);
}

This loops over all the key/value pairs in the object obj and displays their names and values. In this case, the output looks like the following:

Name: width, Value: 3
Name: length, Value: 1.5
Name: color, Value: orange

The Iterator() around obj is not necessary in JavaScript 1.7; however, it is needed for JavaScript 1.8. This is to allow destructuring assignment with arrays (see {{ Bug(366941) }}).

Looping across values in an array of objects

You can loop over an array of objects, pulling out fields of interest from each object:

var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for each (let {name: n, family: { father: f } } in people) {
  console.log("Name: " + n + ", Father: " + f);
}

This pulls the name field into n and the family.father field into f, then prints them. This is done for each object in the people array. The output looks like this:

Name: Mike Smith, Father: Harry Smith
Name: Tom Jones, Father: Richard Jones

Pulling fields from objects passed as function parameter

function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name}})
  console.log(displayName + " is " + name);
}

var user = {id: 42, displayName: "jdoe", fullName: {firstName: "John", lastName: "Doe"}};

console.log("userId: " + userId(user));
whois(user);

This pulls the id, displayName and firstName from the user object and prints them.

Ignoring some returned values

You can also ignore return values that you're not interested in:

function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log("A is " + a + " B is " + b);

After running this code, a is 1 and b is 3. The value 2 is ignored. You can ignore any (or all) returned values this way. For example:

[,,] = f();

Pulling values from a regular expression match

When the regular expression exec() method finds a match, it returns an array containing first the entire matched portion of the string and then the portions of the string that matched each parenthesized group in the regular expression. Destructuring assignment allows you to pull the parts out of this array easily, ignoring the full match if it is not needed.

// Simple regular expression to match http / https / ftp-style URLs.
var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
if (!parsedURL)
  return null;
var [, protocol, fullhost, fullpath] = parsedURL;u

Quelltext der Version

<div>
  {{ Fx_minversion_header(2) }}</div>
<p>JavaScript 1.7 ist ein Update für die Sprache, womit mehrere neue Features wie Generatoren, Iteratoren, Array-Comprehensions, <code>let</code>-Ausdrücke, und destructing assignments hinzugefügt wurden. Es enthält außerdem alle Features von <a href="/en-US/docs/JavaScript/New_in_JavaScript/1.6" title="en-US/docs/New_in_JavaScript_1.6">JavaScript 1.6</a>.</p>
<p>Die Unterstützung von JavaScript 1.7 beginnt mit Firefox 2.</p>
<p>Die in diesem Artikel enthaltenen Code-Beispiele können in der JavaScript-Shell getestet werden. Lesen Sie <a href="/en-US/docs/SpiderMonkey/Introduction_to_the_JavaScript_shell" title="en-US/docs/Introduction_to_the_JavaScript_shell">Introduction to the JavaScript shell</a>, um mehr über die Benutzung der Shell zu lernen.</p>
<h2 id="Verwendung_von_JavaScript_1.7">Verwendung von JavaScript 1.7</h2>
<p>Möchte man einige der neuen Features von JavaScript 1.7 verwenden, sollte man dies angeben. Bei HTML oder XUL z. B. wie folgt:</p>
<div style="width:auto;overflow:hidden;">
  <pre class="brush: html">
&lt;script type="application/javascript;version=1.7"&gt;&lt;/script&gt;</pre>
</div>
<p>Bei der Verwendung der <a href="/en-US/docs/SpiderMonkey/Introduction_to_the_JavaScript_shell" title="en-US/docs/Introduction_to_the_JavaScript_shell">JavaScript-Shell</a> gibt man die Version über den Parameter <code>-version 170</code> auf der Kommandozeile an oder benutzt die Funktion <code>version()</code>:</p>
<div style="width: auto;overflow:hidden">
  <pre class="brush:js">
version(170);
</pre>
</div>
<p>Neue Features bei denen die neuen Schüsselwörtern wie <code>yield</code> und <code>let</code> zum Einsatz kommen, setzen die Versionsangabe voraus, da bei existierendem Code diese Schlüsselwörter eventuell bereits als Bezeichner für Variablen oder Funktionen verwendet werden. Solche Features, die keine neuen Schlüsselwörter einführen (destructing assignments und Array-Comprehensions) können ohne die Versionsangabe verwendet werden.</p>
<h2 id="Generatoren_und_Iteratoren_(siehe_Iteratoren_und_Generatoren)">Generatoren und Iteratoren (siehe <a href="/de/docs/JavaScript/Guide/Iteratoren_und_Generatoren" title="en-US/docs/Core_JavaScript_1.5_Guide/Iterators_and_Generators">Iteratoren und Generatoren</a>)</h2>
<p>Bei der Entwicklung von Code, in dem iterative Algorithmen eingesetzt werden (wie z. B. Iterieren über Listen, XML-Nodes, Datenbank-Ausgaben; oder wiederholtes Verarbeiten desselben Datensatzes) gibt es oft Status-Variablen, deren Werte während des Verbeitungsprozesses verändert werden müssen. Tradiotionell müssen die vorübergehenden Werte dann über eine Callback-Funktion bezogen werden.</p>
<h3 id="Generatoren">Generatoren</h3>
<p>Hier ein Beispiel mit einem iterativer Algorithmus für die Berechnung von Fibonacci-Zahlen:</p>
<div style="width: auto;overflow:hidden">
  <pre class="brush:js">
function do_callback(num) {
  console.log(num);
}

function fib() {
  var i = 0, j = 1, n = 0;
  while (n &lt; 10) {
    do_callback(i);
    var t = i;
    i = j;
    j += t;
    n++;
  }
}

fib();
</pre>
</div>
<p>Bei diesem Code kommt eine Callback-Routine zum Einsatz, um bei jedem iterativen Schritt des Algorithmus bestimmte Operationen durchzuführen. In diesem Fall wird jede Fibonacci-Zahl einfach auf der Konsole ausgegeben.</p>
<p>Generatoren und Iteratoren arbeiten zusammen, um dies besser umzusetzen. Im Anschluss ein Beispiel zur Berechnung von Fibonacci-Zahlen unter Einsatz eines Generators:</p>
<pre class="brush:js">
function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    var t = i;
    i = j;
    j += t;
  }
}

var g = fib();
for (var i = 0; i &lt; 10; i++) {
  console.log(g.next());
}
</pre>
<p>Bei der Funktion, welche das Schlüsselwort <code>yield</code> enthält, handelt es sich um einen Generator. Beim Aufruf dieser Funktion werden ihre formalen Parameter an aktuelle Argumente gebunden, aber der Code nicht ausgeführt, sondern stattdessen ein Generator-Iterator zurückgegeben. Bei jedem Aufruf der <code>next()</code>-Methode des Generator-Iterators wird dann ein weiterer Iterationsschritt ausgeführt. Der Rückgabewert jedes Durchlaufs ist der nach <code>yield</code> stehende Wert. Man kann sich <code>yield</code> ungefähr wie eine spezielles <code>return</code> für Generator-Iterator-Objekte vorstellen, welches die Begrenzung für jeden Iterationsschritt festlegt. Bei jedem Aufruf von <code>next()</code> wird die Ausführung dann bei der Anweisung nach <code>yield</code> fortgesetzt.</p>
<p>Ein Generator-Iterator wird durchlaufen, indem die Methode <code>next()</code> wiederholt aufgerufen wird, solange bis schließlich das gewünscht Ergebnis erreicht bzw. die Bedingung erfüllt ist. Bei dem Beispiel mit den Fibonacci-Zahlen wird also wiederholt <code>g.next()</code> aufgerufen, bis man die gewünschte Anzahl von Fibonacci-Zahlen erzeugt hat.</p>
<h4 id="Fortsetzen_eines_Generators_an_einem_bestimmten_Punkt">Fortsetzen eines Generators an einem bestimmten Punkt</h4>
<p>Sobald ein Generator einmal durch den Aufruf der <code>next()</code>-Methode gestartet wurde, kann über die Methode <code>send()</code> ein beliebiger Wert an den Generator übergeben werden. Dieser Wert wird dann so interpriert, als wäre es der Wert des letzten <code>yield</code>. Der Generator gibt dann den Operanden des darauf folgenden <code>yield</code> zurück.</p>
<p>Ein Generator lässt sich nicht direkt an einem bestimmten Punkt starten, sondern nur über die Methode <code>next()</code>. Erst nach dem <code>next()</code>-Aufruf kann über <code>send()</code> ein Wert gesetzt werden.</p>
<div class="note">
  <strong>Achtung:</strong> Der Aufruf von <code>send(undefined)</code> ist äquivalent zum Aufruf von <code>next()</code>. Jeder Start eines neuen Generator über <code>send()</code> mit einem anderen Wert als undefined resultiert jedoch in einem <code>TypeError</code>-Ausnahmefehler.</div>
<h4 id="Ausnahmen_bei_Generatoren">Ausnahmen bei Generatoren</h4>
<p>Man kann einen Generator dazu bringen, eine Ausnahme auszuwerfen, indem man seine <code>throw()</code>-Methode aufruft und ihr den Wert übergibt, der ausgeworfen werden soll. Diese Ausnahme wird unter Einbeziehung des Kontext des aktuellen Unterbrechung ausgeworfen, so als wäre das <code>yield</code> des aktuellen Durchlaufs eine Anweisung <code>throw Wert</code><code><em>.</em></code></p>
<p><span style="color:#ff0000;">Trifft die Ausführung während der Verarbeitung der ausgeworfenen Ausnahme auf kein <code>yield</code>, so verbreitet sich die Ausnahme bis nach oben durch den Aufruf bis zu <code>next()</code> und nachfolgende Aufrufe von <code>next()</code> lösen eine <code>StopIteration</code>-Ausnahme aus.</span></p>
<h4 id="Schlie.C3.9Fen_eines_Generators">Schließen eines Generators</h4>
<p>Generatoren besitzen eine Methode <code>close()</code>, welche den Generator zwingt, sich selbst zu schließen. Eine solchen Schließung wirkt sich wie folgt aus:</p>
<ol>
  <li>Jede <code>finally</code>-Klausel, die in der Generator-Funktion aktiv ist, wird ausgeführt.</li>
  <li>Wird durch eine <code>finally</code>-Klausel eine andere Ausnahme als<code> StopIteration</code> ausgeworfen, so wird diese an die Funktion weitergeleitet, die <code>close()</code> aufgerufen hat.</li>
  <li>Der Generator terminiert.</li>
</ol>
<h4 id="Generator-Beispiel">Generator-Beispiel</h4>
<p>Dieser Code arbeitet mit einem Generator, der alle 100 Schleifendurchläufe etwas "abwirft" (yield = abwerfen):</p>
<pre class="brush:js">
var gen = generator();

function driveGenerator() {
  if (gen.next()) {
    window.setTimeout(driveGenerator, 0);	
  } else {
    gen.close();	
  }
}

function generator() {
  while (i &lt; something) {
    /** stuff **/

    ++i;
    /** 100 loops per yield **/
    if ((i % 100) == 0) {
      yield true;
    } 
  }
  yield false;
}
</pre>
<h3 id="Iteratoren">Iteratoren</h3>
<p>Ein <em>Iterator</em> ist ein spezielles Objekt, das es erlaubt über Daten zu iterieren.</p>
<p>Bei der normalen Benutzung sind Iterator-Objekte "unsichtbar"; man braucht sie nicht explizit abzusprechen, sondern setzt stattdessen <a href="/en-US/docs/JavaScript/Guide/Statements#Object_Manipulation_Statements" title="en-US/docs/JavaScript/Guide/Statements#Object Manipulation Statements"><code>for...in</code> und <code>for each...in</code> Anweisungen</a> ein, um über Schlüssel und/oder Werte von Objekten zu iterieren.</p>
<pre class="brush:js">
var objectWithIterator = getObjectSomehow();

for (var i in objectWithIterator)
{
  console.log(objectWithIterator[i]);
}
</pre>
<p>Für die Implementierung eines eigenen Iterator-Objekts oder zur direkten Manipulation von Iteratoren sollte man über die <code>next()</code>-Methode, die <code>StopIteration</code>-Ausnahme und die <code>__iterator__</code>-Methode informiert sein.</p>
<p>Ein Iterator für ein Objekt kann man mit dem Aufruf von <code>Iterator(<em>objectname</em>)</code>; erzeugen. Der Iterator kann über die Methode <code>__iterator__</code> gefunden werden; ist diese Methode nicht vorhanden, handelt es sich um einen Default-Iterator. Ein Default-Iterator wirft über <code>yield</code> die Eigenschaften des Objekts ab. Möchte man stattdessen einen selbstdefinierten Iterator einsetzen, überschreibt man die Methode <code>__iterator__</code>, damit diese eine Instanz des selbstbefinierten Iterators zurückgibt. Um den Iterator eines Objekts über ein Skript abzufragen, sollte man auf <code>Iterator(obj)</code> statt direkt auf <code>__iterator__</code> zurückgreifen. Ersteres funktioniert für Arrays, letzteres nicht.</p>
<p>Nach Erzeugung des Iterators kann man einfach über die Methode <code>next()</code> das nächste Element abfragen. Sind keine Daten mehr vorhanden, wird eine <code>StopIteration</code>-Ausnahme ausgeworfen.</p>
<p>Hier ein einfaches Beispiel für die direkte Manipulation eines Iterators:</p>
<pre class="brush:js">
var obj = {name:"Jack Bauer", username:"JackB", id:12345, agency:"CTU",
          region:"Los Angeles"};

var it = Iterator(obj);

try {
  while (true) {
    print(it.next() + "\n");
  }
} catch (err if err instanceof StopIteration) {
  print("End of record.\n");
} catch (err) {
  print("Unknown error: " + err.description + "\n");
}
</pre>
<p>Die Ausgabe dieses Codes ist wie folgt:</p>
<pre class="eval">
name,Jack Bauer
username,JackB
id,12345
agency,CTU
region,Los Angeles
End of record.
</pre>
<p>Optional kann man bei der Erstellung eines Iterators einen booleschen Wert als zweiten Parameter angeben, womit festgelegt wird, ob nur der jeweilge Schlüssel beim Aufruf der <code>next()</code>-Methode zurückgegeben werden soll. Kommt eine benutzerdefinierte <code>__iterator__</code>-Funktionen zum Einsatz, wird der Wert als einziges Argument an diese übergeben. Würde man beim Beispiel oben die Anweisung <code>var it = Iterator(obj);</code> in <code>var it = Iterator(obj, true);</code> ändern, würde man folgende Ausgabe erhalten:</p>
<pre>
name
username
id
agency
region
End of record.
</pre>
<p>In beiden Fällen kann die Reihenfolge der Datenausgabe - je nach Implemetierung - variieren. Es gibt keine Garantie für eine bestimmte Anordung der ausgegebenen Daten.</p>
<p>Iteroren sind nützlich, um die Daten in einem Objekt abzufragen. Solche Objekte, die Daten enthalten, von denen man zunächst nicht weiß, eingeschlossen. Das kann hilfreich sein, wenn man Daten hinterlegen muss, die von einer Applikation nicht erwartet werden.</p>
<h2 id="Array-Comprehensions_(siehe_Array_comprehensions)">Array-Comprehensions (siehe <a href="/en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Array_comprehensions" title="en-US/docs/JavaScript/Guide/Predefined_Core_Objects#Array_comprehensions">Array comprehensions</a>)</h2>
<p>Array-Comprehensions nutzen Generatoren für die effiziente Initialisierung von Arrays. Zum Beispiel:</p>
<pre class="brush:js">
function range(begin, end) {
  for (let i = begin; i &lt; end; ++i) {
    yield i;
  }
}
</pre>
<p><code>range()</code> ist ein Generator, der alle Werte zwischen <var>begin</var> und <var>end</var> zurückgibt. Nach der Definition kann der Generator wie folgt benutzt werden:</p>
<pre class="brush:js">
var ten_squares = [i * i for each (i in range(0, 10))];
</pre>
<p>Damit wird ein Array <em>ten_squares</em> vorinitialisiert, welches die Qudratzahlen der Werte von <code>0</code> bis <code>9</code> enthält.</p>
<p>Bei der Initialisierung können beliebige Bedingungen angegeben werden. Mit folgendem Code wird z. B. ein Array initialisiert, welches die geraden Zahlen zwischen 0 und 20 enthält:</p>
<pre class="brush:js">
var evens = [i for each (i in range(0, 21)) if (i % 2 == 0)];
</pre>
<p>Bei Versionen vor JavaScript 1.7 würde man dies ungefähr so umsetzen:</p>
<pre class="brush:js">
var evens = [];
for (var i=0; i &lt;= 20; i++) {
  if (i % 2 == 0)
    evens.push(i);
}
</pre>
<p>Die Array-Comprehension ist nicht nur kompakter, sondern auch lesbarer, sobald man das Konzept einmal verstanden hat.</p>
<h3 id="Regeln_f.C3.BCr_die_Sichtbarkeit_(Scope)">Regeln für die Sichtbarkeit (Scope)</h3>
<p>Array-Comprehensions sind von einen impliziten Block abgegrenzt, der alles, was zwischen den eckige Klammern steht, einschließt; inklusive impliziter <code>let</code>-Deklarationen.</p>
<h2 id="Block-Begrenzungen_mit_let_(siehe_let_Statement)">Block-Begrenzungen mit <code>let</code> (siehe <a href="/en-US/docs/JavaScript/Reference/Statements/let" title="en-US/docs/JavaScript/Reference/Statements/let"><code>let</code> Statement</a>)</h2>
<p>Es gibt verschiedene Möglichkeiten, wie mit <code>let</code> Blockbegrenzungen von Daten und Funktionen verwaltet werden können.</p>
<ul>
  <li>Die <a href="#let_statement"><strong><code>let</code>-Anweisung</strong></a> ermöglicht die Zuweisung von Werten an Variable innerhalb des Sichtbarkeitsbereichs eines Blocks, ohne dass Werten gleichnamiger Variablen außerhalb dieses Blocks beeinflusst werden.</li>
  <li>Mit dem <a href="#let_expressions"><strong><code>let</code>-Ausdruck</strong></a> können Variablen erzeugt werden, die nur für einen einzelnen Ausdruck gelten.&nbsp;</li>
  <li>Die <a href="#let_definitions"><strong><code>let</code>-Definition</strong></a> definiert Variablen, dessen Sichtbarkeitsbereich durch den Block in dem sie definiert wurden, bestimmt wird. Diese Syntax ist der von <code>var</code> sehr ähnlich.</li>
  <li>Außerdem können mit <code>let</code>&nbsp; <a href="#let-scoped_variables_in_for_loops">Variablen erzeugt werden, die nur innerhalb des Kontext einer for-Schleife</a> sichtbar sind.</li>
</ul>
<h3 id="let-Anweisung"><code>let-Anweisung</code></h3>
<p>Die let-Anweisung ermöglicht die Erzeugung eines lokalen Sichtbarkeitsbereichs für Variablen. Eine oder mehrere Variablen werden an die lexikalische Begrenzung eines einzelnen Blocks gebunden. Andernfalls ist es exakt das Gleiche wie eine <a href="/en-US/docs/JavaScript/Reference/Statements/block" title="/en-US/docs/JavaScript/Reference/Statements/block">Block-Anweisung</a>. Der Sichtbarkeitsbereich einer mit <code>var</code> deklarierten Variablen ist allerdings - auch wenn sie innerhalb der <code>let</code>-Anweisung deklariert wurde - noch immer der Sichtbarkeitsbreich der Funktion. Mit <code>var</code> deklarierten Variablen verhalten sich also exakt gleich, wenn sie innerhalb oder außerhalb der <code>let</code>-Anweisung deklariert werden - sie befinden sich im Sichtbarkeitsbereich der Funktion.</p>
<p>Zum Beispiel:</p>
<pre class="brush:js">
var x = 5;
var y = 0;

let (x = x+10, y = 12) {
  console.log(x+y); // 27
}

console.log(x + y); // 5
</pre>
<p>Die Regeln für den Code-Block sind dieselben wie bei jedem anderen Block bei JavaScript. Mit Hilfe der <code>let</code>-Declarationen könnten eigene lokale Variablen bestimmt werden.</p>
<div class="note">
  <strong>Achtung:</strong> Bei der Syntax für&nbsp; <code>let</code>-Anweisungen sind die Klammern nach let nicht optional, sondern müssen unbedingt angegeben werden; das Weglassen der Klammern resultiert in einem Syntaxfehler.</div>
<h4 id="Regeln_f.C3.BCr_den_Sichtbarkeitsbereich_(Scope)">Regeln für den Sichtbarkeitsbereich (Scope)</h4>
<p>Der Sichtbarkeitsbereich von Variablen, die mit <code>let</code> deklariert werden, ist der <code>let</code>-Block selbst, Blöcke innerhalb dieses Blocks eingeschlossen - solange sie Variablen mit den gleichen Namen definieren.</p>
<h3 id="let-Ausdr.C3.BCcke"><code>let</code>-Ausdrücke</h3>
<p>Mit <code>let</code> kann die Sichtbarkeit von Variablen auf einzelne Ausdrücke beschränkt werden:</p>
<pre class="brush:js">
var x = 5;
var y = 0;
console.log(let(x = x + 10, y = 12) x + y);
console.log(x + y);
</pre>
<p>Ausgabe:</p>
<pre>
27
5
</pre>
<p>In diese Fall ist der Sichtbarkeitsbereich für die Variablen <var>x</var> und <var>y</var> bei den Zuweisungen der Werte <code>x+10</code> und <code>12</code> auf den Ausdruck <code>x + y + "&lt;br&gt;\n"</code> beschränkt.</p>
<h4 id="Regeln_f.C3.BCr_die_Sichtarkeit_(Scope)">Regeln für die Sichtarkeit (Scope)</h4>
<p>Gegeben ist ein <code>let</code>-Ausdruck:</p>
<pre class="eval">
let (<var>decls</var>) <var style="color: blue;">expr</var>
</pre>
<p>Dann wird um <var style="color: blue;">expr</var> herum ein impliziter Block erzeugt.</p>
<h3 id="let-Definitionen"><code>let</code>-Definitionen</h3>
<p>Das Schlüsselwort <code>let</code> kann auch für die Definition von Variablen in einem Block verwendet werden.</p>
<div class="note">
  <strong>Achtung:</strong> Falls Ihnen mehr interessante Beispiele einfallen, fügen Sie diese bitte hinzu.</div>
<pre class="brush:js">
if (x &gt; y) {
  let gamma = 12.7 + y;
  i = gamma * x;
}
</pre>
<p><span style="color:#ff0000;">You can use <code>let</code> definitions to alias pseudo-namespaced code in extensions.</span> (See <a href="https://developer.mozilla.org/en-US/docs/Security_best_practices_in_extensions" title="en-US/docs/Security_best_practices_in_extensions">Security best practices in extensions</a>.)</p>
<pre class="brush:js">
let Cc = Components.classes, Ci = Components.interfaces;
</pre>
<p><code>let</code>-Anweisungen, -Ausdrücke und -Definitionen sorgen manchmal für saubereren Code, wenn innere Funktionen benutzt werden:</p>
<pre class="brush:js">
var list = document.getElementById("list");

for (var i = 1; i &lt;= 5; i++) {
  var item = document.createElement("LI");
  item.appendChild(document.createTextNode("Item " + i));

  let j = i;
  item.onclick = function (ev) {
    alert("Item " + j + " is clicked.");
  };
  list.appendChild(item);
}
</pre>
<p>Der Code funktioniert wie erwartet, da die fünf Instanzen der (anonymen) inneren Funktion mit fünf unterschiedlichen Instanzen der Variablen <code>j </code>arbeiten. Der Code würde so nicht funktionieren, wenn man <code>var</code> statt <code>let</code> verwenden oder die Variable <code>j</code> entfernen und einfach die Variable <code>i</code> in der inneren Funktion benutzen würde.</p>
<h4 id="Regeln_f.C3.BCr_den_Sichtbarkeitsbereich_(Scope)">Regeln für den Sichtbarkeitsbereich (Scope)</h4>
<p>Durch <code>let</code> deklarierte Variablen sind in dem Block in dem sie definiert wurden sichtbar, als auch in jedem inneren Block, sofern sie darin nicht neu definiert wurden. Hier verhält sich <code>let</code> also sehr ähnlich wie <code>var</code>. Der größte Unterschied besteht darin, dass bei <code>var</code>-Variablen der Sichtbarkeitsbereich die ganze einschließende Funktion ist:</p>
<pre class="brush:js">
function varTest() {
  var x = 31;
  if (true) {
    var x = 71;  // dieselbe Variable!
    alert(x);  // 71
  }
  alert(x);  // 71
}

function letTest() {
  let x = 31;
  if (true) {
    let x = 71;  // andere Variable!
    alert(x);  // 71
  }
  alert(x);  // 31
}
</pre>
<p>Der Ausdruck auf der rechten Seite des Gleichzeichens ist innerhalb des Blocks, anders als bei <code>let</code>-Ausdrücken und <code>let</code>-Anweisungen:</p>
<pre class="brush:js">
function letTests() {
  let x = 10;

  // let-Anweisung
  let (x = x + 20) {
    alert(x);  // 30
  }

  // let-Ausdruck
  alert(let (x = x + 20) x);  // 30

  // let-Definition
  {
    let x = x + 20;  // x here evaluates to undefined
    alert(x);  // undefined + 20 ==&gt; NaN
  }
}
</pre>
<p>Beim Top-Level von Skripten und Funktionen verhält sich <code>let</code> exakt wie <code>var</code>. Zum Beispiel:</p>
<pre class="brush:js">
var x = 'global';
let y = 'global';
console.log(this.x);
console.log(this.y);
</pre>
<p>Die Ausgabe ist hier zweimal "global".</p>
<div class="note">
  <strong>Achtung:</strong> Die globalen Sichtbarkeitsregeln von <code>let</code>-Definitionen ändern sich voraussichtlich bei ES6.</div>
<h3 id="let-scoped_variables_in_for_loops"><code>let</code>-Variablen in <code>for</code>-Schleifen</h3>
<p>Mit Hilfe von <code>let</code> können Variablen lokal an den Sichtbarkeitsbereich einer <code>for</code>-Schleife gebunden werden. Im Kopf der Schleife definierte <code>var</code>-Variablen sind hingegen innerhalb der ganzen Funktion sichtbar.</p>
<pre class="brush:js">
var i=0;
for ( let i=i ; i &lt; 10 ; i++ )
  console.log(i);

for ( let [name,value] in Iterator(obj) )
  console.log("Name: " + name + ", Value: " + value);
</pre>
<h4 id="Scoping_rules">Scoping rules</h4>
<pre class="eval">
for (let <var>expr1</var>; <var style="color: blue;">expr2</var>; <var style="color: blue;">expr3</var>) <var style="color: blue;">statement</var>
</pre>
<p>In this example, <var style="color: blue;">expr2</var>, <var style="color: blue;">expr3</var>, and <var style="color: blue;">statement</var> are enclosed in an implicit block that contains the block local variables declared by <code>let <var>expr1</var></code>. This is demonstrated in the first loop above.</p>
<pre class="eval">
for (let <var>expr1</var> in <var>expr2</var>) <var style="color: blue;">statement</var>
for each(let <var>expr1</var> in <var>expr2</var>) <var style="color: blue;">statement</var>
</pre>
<p>In both these cases, there are implicit blocks containing each <var style="color: blue;">statement</var>. The first of these is shown in the second loop above.</p>
<h2 id="Destructuring_assignment_(Merge_into_own_page.2Fsection)"><a href="/en-US/docs/JavaScript/Syntax/Destructuring_assignment" title="/en-US/docs/JavaScript/Syntax/Destructuring_assignment">Destructuring assignment</a> (Merge into own page/section)</h2>
<p>Destructuring assignment makes it possible to extract data from arrays or objects using a syntax that mirrors the construction of array and object literals.</p>
<p>The object and array literal expressions provide an easy way to create ad-hoc packages of data. Once you've created these packages of data, you can use them any way you want to. You can even return them from functions.</p>
<p>One particularly useful thing you can do with destructuring assignment is to read an entire structure in a single statement, although there are a number of interesting things you can do with them, as shown in the section full of examples that follows.</p>
<p>This capability is similar to features present in languages such as Perl and Python.</p>
<h3 id="Examples">Examples</h3>
<p>Destructuring assignment is best explained through the use of examples, so here are a few for you to read over and learn from.</p>
<h4 id="Avoiding_temporary_variables">Avoiding temporary variables</h4>
<p>You can use destructuring assignment, for example, to swap values:</p>
<pre class="brush:js">
var a = 1;
var b = 3;

[a, b] = [b, a];
</pre>
<p>After executing this code, <var>b</var> is 1 and <var>a</var> is 3. Without destructuring assignment, swapping two values requires a temporary variable (or, in some low-level languages, the <a class="external" href="http://en.wikipedia.org/wiki/XOR_swap">XOR-swap trick</a>).</p>
<p>Similarly, it can be used to rotate three or more variables:</p>
<pre class="brush:js">
var a = 'o', 
    b = "&lt;span style='color:green;'&gt;o&lt;/span&gt;", 
    c = 'o', 
    d = 'o', 
    e = 'o', 
    f = "&lt;span style='color:blue;'&gt;o&lt;/span&gt;", 
    g = 'o',
    h = 'o';

for ( var lp=0; lp &lt; 40; lp++ ) {

  [a, b, c, d, e, f, g, h] = [b, c, d, e, f, g, h, a];

  document.write(a+''+b+''+c+''+d+''+e+''+f+''+g+''+h+''+"&lt;br /&gt;");

}
</pre>
<p>After executing this code, a visual colorful display of the variable rotation will be displayed.</p>
<p>Returning to our Fibonacci generator example from above, we can eliminate the temporary "t" variable by computing the new values of "i" and "j" in a single group-assignment statement:</p>
<pre class="brush:js">
function fib() {
  var i = 0, j = 1;
  while (true) {
    yield i;
    [i, j] = [j, i + j];
  }
}

var g = fib();
for (let i = 0; i &lt; 10; i++)
  print(g.next());
</pre>
<h4 id="Multiple-value_returns">Multiple-value returns</h4>
<p>Thanks to destructuring assignment, functions can return multiple values. While it's always been possible to return an array from a function, this provides an added degree of flexibility.</p>
<pre class="brush:js">
function f() {
  return [1, 2];
}
</pre>
<p>As you can see, returning results is done using an array-like notation, with all the values to return enclosed in brackets. You can return any number of results in this way. In this example, <code>f()</code> returns the values <code>{{ mediawiki.external('1, 2') }}</code> as its output.</p>
<pre class="brush:js">
var a, b;
[a, b] = f();
console.log("A is " + a + " B is " + b);
</pre>
<p>The statement <code>{{ mediawiki.external('a, b') }} = f()</code> assigns the results of the function to the variables in brackets, in order: <var>a</var> is set to 1 and <var>b</var> is set to 2.</p>
<p>You can also retrieve the return values as an array:</p>
<pre class="brush:js">
var a = f();
console.log("A is " + a);
</pre>
<p>In this case, <var>a</var> is an array containing the values 1 and 2.</p>
<h4 id="Looping_across_objects">Looping across objects</h4>
<p>You can also use destructuring assignment to pull data out of an object:</p>
<pre class="brush:js">
let obj = { width: 3, length: 1.5, color: "orange" };

for (let [name, value] in Iterator(obj)) {
  console.log("Name: " + name + ", Value: " + value);
}
</pre>
<p>This loops over all the key/value pairs in the object <var>obj</var> and displays their names and values. In this case, the output looks like the following:</p>
<pre class="eval">
Name: width, Value: 3
Name: length, Value: 1.5
Name: color, Value: orange
</pre>
<p>The <code>Iterator()</code> around <code>obj</code> is not necessary in JavaScript 1.7; however, it is needed for <a href="/en-US/docs/JavaScript/New_in_JavaScript/1.8" title="en-US/docs/New_in_JavaScript_1.8">JavaScript 1.8</a>. This is to allow destructuring assignment with arrays (see {{ Bug(366941) }}).</p>
<h4 id="Looping_across_values_in_an_array_of_objects">Looping across values in an array of objects</h4>
<p>You can loop over an array of objects, pulling out fields of interest from each object:</p>
<pre class="brush:js">
var people = [
  {
    name: "Mike Smith",
    family: {
      mother: "Jane Smith",
      father: "Harry Smith",
      sister: "Samantha Smith"
    },
    age: 35
  },
  {
    name: "Tom Jones",
    family: {
      mother: "Norah Jones",
      father: "Richard Jones",
      brother: "Howard Jones"
    },
    age: 25
  }
];

for each (let {name: n, family: { father: f } } in people) {
  console.log("Name: " + n + ", Father: " + f);
}
</pre>
<p>This pulls the <var>name</var> field into <var>n</var> and the <var>family.father</var> field into <var>f</var>, then prints them. This is done for each object in the <var>people</var> array. The output looks like this:</p>
<pre>
Name: Mike Smith, Father: Harry Smith
Name: Tom Jones, Father: Richard Jones</pre>
<h4 id="Pulling_fields_from_objects_passed_as_function_parameter">Pulling fields from objects passed as function parameter</h4>
<pre class="brush:js">
function userId({id}) {
  return id;
}

function whois({displayName: displayName, fullName: {firstName: name}})
  console.log(displayName + " is " + name);
}

var user = {id: 42, displayName: "jdoe", fullName: {firstName: "John", lastName: "Doe"}};

console.log("userId: " + userId(user));
whois(user);</pre>
<p>This pulls the <code>id</code>, <code>displayName</code> and<span class="Apple-converted-space"> </span><code>firstName</code><span class="Apple-converted-space"> </span>from the user object and prints them.</p>
<h4 id="Ignoring_some_returned_values">Ignoring some returned values</h4>
<p>You can also ignore return values that you're not interested in:</p>
<pre class="brush:js">
function f() {
  return [1, 2, 3];
}

var [a, , b] = f();
console.log("A is " + a + " B is " + b);
</pre>
<p>After running this code, a is 1 and b is 3. The value 2 is ignored. You can ignore any (or all) returned values this way. For example:</p>
<pre class="brush:js">
[,,] = f();
</pre>
<h4 id="Pulling_values_from_a_regular_expression_match">Pulling values from a regular expression match</h4>
<p>When the regular expression <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec" title="en-US/docs/Core_JavaScript_1.5_Reference/Global_Objects/RegExp/exec"> exec()</a></code> method finds a match, it returns an array containing first the entire matched portion of the string and then the portions of the string that matched each parenthesized group in the regular expression. Destructuring assignment allows you to pull the parts out of this array easily, ignoring the full match if it is not needed.</p>
<pre class="brush:js">
// Simple regular expression to match http / https / ftp-style URLs.
var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url);
if (!parsedURL)
  return null;
var [, protocol, fullhost, fullpath] = parsedURL;u</pre>
Zu dieser Version zurücksetzen