diff options
Diffstat (limited to 'files/de/web/javascript/reference/iteration_protocols/index.html')
-rw-r--r-- | files/de/web/javascript/reference/iteration_protocols/index.html | 349 |
1 files changed, 349 insertions, 0 deletions
diff --git a/files/de/web/javascript/reference/iteration_protocols/index.html b/files/de/web/javascript/reference/iteration_protocols/index.html new file mode 100644 index 0000000000..f1ecbe29a1 --- /dev/null +++ b/files/de/web/javascript/reference/iteration_protocols/index.html @@ -0,0 +1,349 @@ +--- +title: Iterations Protokolle +slug: Web/JavaScript/Reference/Iteration_protocols +tags: + - ECMAScript 2015 + - Intermediate + - Iterable + - Iterator + - JavaScript +translation_of: Web/JavaScript/Reference/Iteration_protocols +--- +<div>{{jsSidebar("More")}}</div> + +<p>Einige Änderungen in ECMAScript 2015 sind keine neuen Objekte oder Syntax, sondern Protokolle. Diese Protokolle können von jedem Objekt implementiert werden, wenn einige Konventionen eingehalten werden.</p> + +<p>Es gibt zwei Protokolle: Das <a href="#Das_Iterierbare_(iterable)_Protokoll">Iterierbare (iterable) Protokoll</a> und das <a href="#Das_Iterator_Protokoll">Iterator Protokoll</a></p> + +<h2 id="Das_Iterierbare_iterable_Protokoll">Das Iterierbare (iterable) Protokoll</h2> + +<p>Das <strong>Iterierbare (iterable)</strong> Protokoll erlaubt es bei JavaScript-Objekten das Iterierverhalten zu definieren oder anzupassen, wie z. B. wie Werte in einem {{jsxref("Statements/for...of", "for..of")}} Konstrukt durchlaufen werden. Einige Standardtypen sind von sich aus schon Iterierbar mit einem Standarditerationsverhalten, so wie {{jsxref("Array")}} oder {{jsxref("Map")}}, wohingegen andere Typen (so wie {{jsxref("Object")}}) nicht Iterierbar sind.</p> + +<p>Um <strong>Iterierbar</strong> zu sein, muss ein Objekt die <strong>@@iterator</strong> Methode implementieren, was bedeutet, dass das Objekte (oder ein Objekt weiter oben in der <a href="/de/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">Prototypenkette</a>) eine Eigenschaft mit dem <strong>@@iterator</strong> Schlüssel haben muss, welcher über die Konstante <code>{{jsxref("Symbol.iterator")}}</code> erreichbar ist:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Eigenschaft</th> + <th scope="col">Wert</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>[Symbol.iterator]</code></td> + <td>Eine Funktion ohne Parameter, welche ein Objekt zurückgibt, welches dem <a href="#Das_Iterator_Protokoll">Iterator Protokoll</a> entspricht.</td> + </tr> + </tbody> +</table> + +<p>Immer wenn ein Objekt iteriert werden soll (z. B. am Anfang einer <code>for..of</code> Schleife), wird die <code>@@iterator</code> Methode mit keinem Argument aufgerufen und der zurückgegebene <strong>Iterator</strong> wird benutzt, um die zu iterierenden Werte zu bekommen.</p> + +<h2 id="Das_Iterator_Protokoll">Das Iterator Protokoll</h2> + +<p>Das <strong>Iterator</strong> Protokoll definiert einen Standardweg, um eine Sequenz von Werte (endlich oder unendlich lang) zu produzieren.</p> + +<p>Ein Objekt ist ein Iterator, wenn es die Methode <code><strong>next()</strong></code> mit folgender Semantik implementiert:</p> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Eigenschaft</th> + <th scope="col"><code>Wert</code></th> + </tr> + <tr> + <td><code>next</code></td> + <td> + <p>Eine Funktion ohne Parameter, welche ein Objekt mit zwei Eigenschaften zurückgibt:</p> + + <ul> + <li><code>done</code> (boolean) + + <ul> + <li>Hat den Wert <code>true</code>, wenn der Iterator das Ende der Iterierten Sequenz erreicht hat. In diesem Fall ist <code>value</code> ein optional spezifizierter Rückgabewert des Iterators. Der Rückgabewert ist <a href="http://www.2ality.com/2013/06/iterators-generators.html#generators-as-threads">hier</a> näher erklärt.</li> + <li>Hat den Wert <code>false</code>, wenn der Iterator weitere Werte aus der Sequenz produzieren kann. Äquivalent ist, wenn die <code>done</code> Eigenschaft nicht definiert wird.</li> + </ul> + </li> + <li><code>value</code> - ein JavaScript Wert, der vom Iterator zurückgegeben wird. Kann weggelassen werden, wenn <code>done</code> den Wert <code>true</code> hat.</li> + </ul> + + <p>Die <code>next</code> Methode gibt immer ein Objekt mit den Eigenschaften <code>done</code> und <code>value</code> zurück. Wird kein Objekt zurückgegeben (wie z. B. <code>false</code> oder <code>undefined</code>), wird ein {{jsxref("TypeError")}} ("iterator.next() returned a non-object value") erzeugt.</p> + </td> + </tr> + </tbody> +</table> + +<p>Einige Iteratoren sind wiederum iterierbar:</p> + +<pre class="brush: js">var someArray = [1, 5, 7]; +var someArrayEntries = someArray.entries(); + +someArrayEntries.toString(); // "[object Array Iterator]" +someArrayEntries === someArrayEntries[Symbol.iterator](); // true +</pre> + +<h2 id="Beispiele_für_den_Einsatz_de_Iterations_Protokolle">Beispiele für den Einsatz de Iterations Protokolle</h2> + +<p>Ein {{jsxref("String")}} ist ein Beispiel für ein standard iterierbares Objekt:</p> + +<pre class="brush: js">var someString = 'hi'; +typeof someString[Symbol.iterator]; // "function" +</pre> + +<p>Der <a href="/de/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator">Standard Iteratior</a> von <code>String</code>s gibt die Codepoints einen nach dem anderen zurück:</p> + +<pre class="brush: js">var iterator = someString[Symbol.iterator](); +iterator + ''; // "[object String Iterator]" + +iterator.next(); // { value: "h", done: false } +iterator.next(); // { value: "i", done: false } +iterator.next(); // { value: undefined, done: true }</pre> + +<p>Einige Standardkonstrukte, wie z. B. die <a href="/de/docs/Web/JavaScript/Reference/Operators/Spread_operator">Spread Syntax</a>, benutzen unter der Decke das selbe Iterierbare Protokoll</p> + +<pre class="brush: js">[...someString] // ["h", "i"]</pre> + +<p>Man kann das Iterierverhalben neu definieren indem eine eigene <code>@@iterator</code> Eigenschaft definiert wird:</p> + +<pre class="brush: js">var someString = new String('hi'); // need to construct a String object explicitly to avoid auto-boxing + +someString[Symbol.iterator] = function() { + return { // this is the iterator object, returning a single element, the string "bye" + next: function() { + if (this._first) { + this._first = false; + return { value: 'bye', done: false }; + } else { + return { done: true }; + } + }, + _first: true + }; +}; +</pre> + +<p>Zu bemerken ist, dass die Neudefinition von <code>@@iterator</code> hat Effekte auf Standardkonstrukte, die das Iterierbare Protokoll benutzen;</p> + +<pre class="brush: js">[...someString]; // ["bye"] +someString + ''; // "hi" +</pre> + +<h2 id="Iterierbare_Beispiele">Iterierbare Beispiele</h2> + +<h3 id="Standard_iterierbare_Objekte">Standard iterierbare Objekte</h3> + +<p>{{jsxref("String")}}, {{jsxref("Array")}}, {{jsxref("TypedArray")}}, {{jsxref("Map")}} und {{jsxref("Set")}} sind im Standard iterierbar, weil jeder Prototyp der Objekte eine <code>@@iterator</code> Methode definiert.</p> + +<h3 id="Benutzerdefiniertes_Iterierbares_Objekt">Benutzerdefiniertes Iterierbares Objekt</h3> + +<p>Man kann eigene Iterierbare Objekte wie folgt erstellen:</p> + +<pre class="brush: js">var myIterable = {}; +myIterable[Symbol.iterator] = function* () { + yield 1; + yield 2; + yield 3; +}; +[...myIterable]; // [1, 2, 3] +</pre> + +<h3 id="Standard_APIs_akzeptieren_Iterierbare_Objekte">Standard APIs akzeptieren Iterierbare Objekte</h3> + +<p>Es gibt viele APIs, die iterierbare Objekte akzeptieren, zum Beispiel: {{jsxref("Map", "Map([iterable])")}}, {{jsxref("WeakMap", "WeakMap([iterable])")}}, {{jsxref("Set", "Set([iterable])")}} and {{jsxref("WeakSet", "WeakSet([iterable])")}}:</p> + +<pre class="brush: js">var myObj = {}; +new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b" +new WeakMap([[{}, 'a'], [myObj, 'b'], [{}, 'c']]).get(myObj); // "b" +new Set([1, 2, 3]).has(3); // true +new Set('123').has('2'); // true +new WeakSet(function* () { + yield {}; + yield myObj; + yield {}; +}()).has(myObj); // true +</pre> + +<p>Zudem sollten {{jsxref("Promise.all", "Promise.all(iterable)")}}, {{jsxref("Promise.race", "Promise.race(iterable)")}}, and {{jsxref("Array.from", "Array.from()")}} angeschaut werden.</p> + +<h3 id="Syntaxen_die_iterierbare_Objekte_erwarten">Syntaxen die iterierbare Objekte erwarten</h3> + +<p>Einige Statements und Ausdrücke erwarten iterierbare Objekt, zum Beispiel die <code><a href="/de/docs/Web/JavaScript/Reference/Statements/for...of">for-of</a></code> Schleife, <a href="/de/docs/Web/JavaScript/Reference/Operators/Spread_operator">Spread Syntax</a>, <code><a href="/de/docs/Web/JavaScript/Reference/Operators/yield*">yield*</a></code> und <a href="/de/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">destrukturierende Zuweisungen</a>:</p> + +<pre class="brush: js">for(let value of ['a', 'b', 'c']){ + console.log(value); +} +// "a" +// "b" +// "c" + +[...'abc']; // ["a", "b", "c"] + +function* gen() { + yield* ['a', 'b', 'c']; +} + +gen().next(); // { value:"a", done:false } + +[a, b, c] = new Set(['a', 'b', 'c']); +a // "a" + +</pre> + +<h3 id="Nicht_richtig_definierte_iterierbare_Objekte">Nicht richtig definierte iterierbare Objekte</h3> + +<p>Wenn eine iterierbare <code>@@iterator</code> Methode keinen Iterator Objekt zurück gibt, ist es nicht richtig definiert. Wenn es so benutzt wird, führt das zu Laufzeitfehlern oder unerwartetem Verhalten:</p> + +<pre class="brush: js">var nonWellFormedIterable = {} +nonWellFormedIterable[Symbol.iterator] = () => 1 +[...nonWellFormedIterable] // TypeError: [] is not a function +</pre> + +<h2 id="Iterator_Beispiele">Iterator Beispiele</h2> + +<h3 id="Einfacher_Iterator">Einfacher Iterator</h3> + +<pre class="brush: js">function makeIterator(array) { + var nextIndex = 0; + + return { + next: function() { + return nextIndex < array.length ? + {value: array[nextIndex++], done: false} : + {done: true}; + } + }; +} + +var it = makeIterator(['yo', 'ya']); + +console.log(it.next().value); // 'yo' +console.log(it.next().value); // 'ya' +console.log(it.next().done); // true +</pre> + +<h3 id="Unendlicher_Iterator">Unendlicher Iterator</h3> + +<pre class="brush: js">function idMaker() { + var index = 0; + + return { + next: function(){ + return {value: index++, done: false}; + } + }; +} + +var it = idMaker(); + +console.log(it.next().value); // '0' +console.log(it.next().value); // '1' +console.log(it.next().value); // '2' +// ... +</pre> + +<h3 id="Mit_einem_Generator">Mit einem Generator</h3> + +<pre class="brush: js">function* makeSimpleGenerator(array) { + var nextIndex = 0; + + while (nextIndex < array.length) { + yield array[nextIndex++]; + } +} + +var gen = makeSimpleGenerator(['yo', 'ya']); + +console.log(gen.next().value); // 'yo' +console.log(gen.next().value); // 'ya' +console.log(gen.next().done); // true + + + +function* idMaker() { + var index = 0; + while (true) + yield index++; +} + +var gen = idMaker(); + +console.log(gen.next().value); // '0' +console.log(gen.next().value); // '1' +console.log(gen.next().value); // '2' +// ... +</pre> + +<h3 id="Mit_ES2015_Klassen_class">Mit ES2015 Klassen (class)</h3> + +<pre class="brush: js">class SimpleClass { + constructor(data) { + this.index = 0; + this.data = data; + } + + [Symbol.iterator]() { + return { + next: () => { + if (this.index < this.data.length) { + return {value: this.data[this.index++], done: false}; + } else { + this.index = 0; //If we would like to iterate over this again without forcing manual update of the index + return {done: true}; + } + } + } + }; +} + +const simple = new SimpleClass([1,2,3,4,5]); + +for (const val of simple) { + console.log(val); //'0' '1' '2' '3' '4' '5' +} +</pre> + +<h2 id="Ist_ein_Generator_Objekt_ein_Iterator_oder_ein_iterierbares_Objekt">Ist ein Generator Objekt ein Iterator oder ein iterierbares Objekt?</h2> + +<p>Ein <a href="/de/docs/Web/JavaScript/Reference/Global_Objects/Generator">Generatorobjekt</a> ist beides, Iterator und Iterierbar:</p> + +<pre class="brush: js">var aGeneratorObject = function* () { + yield 1; + yield 2; + yield 3; +}(); +typeof aGeneratorObject.next; +// "function", because it has a next method, so it's an iterator +typeof aGeneratorObject[Symbol.iterator]; +// "function", because it has an @@iterator method, so it's an iterable +aGeneratorObject[Symbol.iterator]() === aGeneratorObject; +// true, because its @@iterator method returns itself (an iterator), so it's an well-formed iterable +[...aGeneratorObject]; +// [1, 2, 3] +</pre> + +<h2 id="Spezifikationen">Spezifikationen</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Spezifikation</th> + <th scope="col">Status</th> + <th scope="col">Kommentar</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-iteration', 'Iteration')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initiale Definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-iteration', 'Iteration')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li>Für mehr Informationen über ES2015 Generatoren, siehe <a href="/de/docs/Web/JavaScript/Reference/Statements/function*">die function* Documentation</a>.</li> +</ul> |