Der Kontrollfluss ist die Reihenfolge, in der der JavaScript-Interpreter ausgeführt wird. Aussagen. Wenn ein Skript keine Anweisungen enthält, die seinen Ablauf ändern, ist es Zeile für Zeile von Anfang bis Ende ausgeführt. Kontrollstrukturen sind wird bestimmt, ob eine Reihe von Anweisungen auf der Grundlage eines eine Reihe von Kriterien festgelegt, eine Reihe von Anweisungen wiederholt ausgeführt oder eine Reihenfolge von Anweisungen.
Bedingte Anweisungen
Bedingte Anweisungen bestimmen, ob Code basierend auf einem oder
weitere Bedingungen. Eine bedingte Anweisung führt den darin enthaltenen Code aus, wenn die
zugehörige Bedingung (oder Gruppe von Bedingungen) wird als true
ausgewertet. Andernfalls wird der
wird der Code übersprungen.
if
...else
else
Eine if
-Anweisung wertet eine Bedingung innerhalb der übereinstimmenden Klammern aus, die
folgen. Wenn die Bedingung in den Klammern true
ergibt,
oder block-Anweisung
nach den übereinstimmenden Klammern ausgeführt:
if ( true ) console.log( "True." );
> "True."
if ( true ) {
const myString = "True.";
console.log( myString );
}
> "True."
Wenn die Bedingung in den Klammern false
ergibt, ist die Anweisung,
wird sie ignoriert:
if ( false ) console.log( "True." );
Ein else
-Keyword, das direkt auf eine if
-Anweisung folgt, und seine
bedingt ausgeführte Anweisung gibt die Anweisung an, die ausgeführt werden soll, wenn die
Die Bedingung if
wird als false
ausgewertet:
if ( false ) console.log( "True." )''
else console.log( "False" );
> "False."
Um mehrere if
-Anweisungen miteinander zu verketten, können Sie
bedingt ausgeführte Anweisung nach else
einer weiteren if
-Anweisung:
const myCondition = 2;
if ( myCondition === 5 ) console.log( "Five." );
else if ( myCondition === 2 ) console.log( "Two." );
Wir empfehlen dringend, die Syntax von Blockanweisungen nach Bedingungen zu verwenden,
verbessert die Lesbarkeit, aber else if
-Klauseln sind oft eine Ausnahme davon:
if ( myCondition === 5 ) {
console.log( "Five." );
} else if ( myCondition === 3 ) {
console.log( "Three" );
} else {
console.log( "Neither five nor three." );
}
> "Neither five nor three."
Ternärer Operator
Mit if
wird eine Anweisung bedingt ausgeführt. Der ternäre Operator (genauer
aber seltener als ternärer Bedingungsoperator bezeichnet) ist eine Kurzschreibweise.
um einen Ausdruck bedingt auszuführen. Wie der Name schon sagt, ist die ternäre
ist der einzige JavaScript-Operator, der drei Operanden verwendet:
- Eine auszuwertende Bedingung, gefolgt von einem Fragezeichen (
?
). - Ausdruck, der ausgeführt werden soll, wenn die Bedingung
true
ergibt, gefolgt von einem Doppelpunkt (:
). - Ausdruck, der ausgeführt werden soll, wenn die Bedingung
false
ergibt.
Dies wird häufig verwendet, um einen Wert bedingt festzulegen oder zu übergeben:
const myFirstResult = true ? "First value." : "Second value.";
const mySecondResult = false ? "First value." : "Second value.";
myFirstResult;
> "First value."
mySecondResult;
> "Second value."
switch
...case
Verwenden Sie die Anweisung switch
, um den Wert eines Ausdrucks mit einer Liste von
potenzielle Werte, die mit einem oder mehreren case
-Keywords definiert werden. Diese Syntax ist
ungewöhnlich, weil es auf einigen der ersten
Designentscheidungen von JavaScript beruht.
In der Syntax switch
...case
wird das Keyword switch
verwendet, gefolgt von einem Ausdruck,
in Klammern gefolgt von einem übereinstimmenden Paar geschweifter Klammern ausgewertet.
Der Text von switch
kann case
Keywords enthalten, in der Regel ein oder mehrere Keywords.
gefolgt von einem Ausdruck oder Wert gefolgt von einem Doppelpunkt (:
).
Wenn der Interpreter einen case
mit einem Wert erreicht, der dem Ausdruck entspricht
wird in der Klammer nach dem Keyword switch
ausgewertet,
, die dieser case
-Klausel folgen:
switch ( 2 + 2 === 4 ) {
case false:
console.log( "False." );
case true:
console.log( "True." );
}
> "True."
Alle Anweisungen, die auf den übereinstimmenden case
folgen, werden ausgeführt, selbst wenn sie
in einer block-Anweisung enthalten.
switch ( 2 + 2 === 4 ) {
case false:
console.log( "False." );
case true:
let myVariable = "True.";
console.log( myVariable );
}
> "True."
Ein Problem bei der Verwendung von switch…case
besteht darin, dass der Parameter
Der JavaScript-Interpreter führt eine beliebige Anweisung aus, die auf das übereinstimmende case
folgt,
auch in anderen case
-Klauseln. Dies wird als „Fall-Through“ bezeichnet. zu den
nächsten case
:
switch ( 2 + 2 === 7 ) {
case false:
console.log( "False." );
case true:
console.log( "True." );
}
> "False."
> "True."
Um ein Fehlschlagen zu vermeiden, beenden Sie jeden Fall mit dem Keyword break
, das
stoppt sofort die Bewertung des switch
-Texts:
switch ( 2 + 2 === 7 ) {
case false:
console.log( "False." );
break;
case true:
console.log( "True." );
break;
}
> "False."
Wenn keine case
mit dem bedingten Wert übereinstimmt, wählt switch
die default
aus
wenn es eine gibt:
switch ( 20 ) {
case 5:
console.log( "The value was five." );
break;
case 10:
console.log( "The value was ten." );
break;
default:
console.log( "The value was something unexpected." );
}
> "The value was something unexpected."
Die Absturzrate gilt jedoch auch für default
, was möglicherweise zu
zu unerwarteten Ergebnissen führen. Um dies zu beheben, beenden Sie die default
-Anweisung mit break
,
oder sie an letzter Stelle in der Fallliste platzieren.
switch ( 20 ) {
default:
console.log( "The value was something unexpected." );
case 10:
console.log( "The value was ten." );
break;
case 5:
console.log( "The value was five." );
break;
}
> The value was something unexpected.
> The value was ten.
Da case
-Klauseln kein
block-Anweisung für die Gruppierung
Bei mehreren Anweisungen werden keine case
- und default
-Anweisungen erstellt.
lexikalischen Geltungsbereich an sich:
let myVariable;
switch ( true ) {
case true:
let myVariable = "True.";
break;
default:
let myVariable = "False.";
break;
}
> Uncaught SyntaxError: redeclaration of let myVariable
Verwenden Sie Blockanweisungen, um den Umfang zu verwalten:
let myVariable;
switch ( true ) {
case true: {
let myVariable = "True.";
break;
}
default: {
let myVariable = "False.";
break;
}
}
Schleifen und Iterationen
Mit Schleifen können Sie Anweisungen wiederholen, solange eine Bedingung erfüllt ist. bis eine Bedingung erfüllt ist. Schleifen verwenden, um eine Reihe von Anweisungen in einem festen bis ein bestimmtes Ergebnis erreicht ist oder bis der das Ende einer iterierbaren Datenstruktur erreicht (zum Beispiel das letzte Element in ein Array, eine Map oder eine Gruppe, die letzte Eigenschaft eines Objekts oder das letzte Zeichen in eine Zeichenfolge).
Loops unterbrechen „Von oben nach unten“ der Ausführung eines Skripts durch Iteration über eine Reihe von Anweisungen, bis eine oder mehrere Bedingungen erfüllt sind oder nicht mehr erfüllt sind. Dies hängt von der Syntax ab, die zum Erstellen der Schleife verwendet wurde. Nach dem Ende der Schleife die Ausführung auf die folgenden Anweisungen an. Im folgenden Beispiel Die Anweisungen im Hauptteil der Schleife werden dreimal vor der geht der Dolmetscher weiter:
let iterationCount = 0;
console.log( "Pre-loop." );
while( iterationCount < 3 ) {
iterationCount++;
console.log( "Loop iteration." );
}
console.log( "Continuing on." );
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Continuing on."
Wenn die Bedingungen während der Ausführung der Schleife nicht erfüllt werden können, wird die Schleife fortgesetzt. auf unbestimmte Zeit. Diese Endlosschleifen sind ein häufiges Problem bei der Programmierung, dazu führen, dass der Haupt-Ausführungsthread oder sogar einen Browsertab zum Absturz bringen.
Das folgende Beispiel wird ausgeführt, solange der boolesche Wert true
beibehalten wird.
true
Da boolesche Werte unveränderlich sind,
entsteht eine Endlosschleife.
console.log( "Pre-loop." );
while( true ) {
console.log( "Loop iteration." );
}
> "Pre-loop."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
> "Loop iteration."
…
Vermeiden Sie Endlosschleifen in Ihrem Produktionscode. Wenn Sie aus Versehen während der Entwicklung behoben werden, können Sie das Problem beheben, indem Sie den aktuellen Browsertab schließen Aktualisieren Sie Ihren Code, damit die Schleife nicht mehr endlos ist, und öffnen Sie die Seite.
while
Eine while
-Schleife wird mit dem Schlüsselwort while
gefolgt von einem Paar von Daten erstellt.
übereinstimmende Klammern mit einer auszuwertenden Bedingung. Wenn die angegebene
Bedingung zuerst true
ergibt, wird die Anweisung (oder
block-Anweisung)
wird ausgeführt. Andernfalls wird die Schleife nie ausgeführt. Nach jedem
wird die Bedingung neu ausgewertet. Ist sie immer noch true
, wird die Schleife
wiederholt wird.
let iterationCount = 0;
while( iterationCount < 3 ) {
iterationCount++;
console.log( `Loop ${ iterationCount }.` );
}
> "Loop 1."
> "Loop 2."
Wenn der Interpreter eine continue
-Anweisung in einer while
-Schleife findet, wird diese Anweisung gestoppt
Iteration, wertet die Bedingung neu aus und setzt die Schleife wenn möglich fort:
let iterationCount = 0;
while( iterationCount <= 5 ) {
iterationCount++;
if( iterationCount === 3 ) {
continue;
}
console.log( `Loop ${ iterationCount }.` );
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Loop 4."
> "Loop 5."
> "Loop ended."
Wenn der Interpreter eine break
-Anweisung in einer while
-Schleife findet, wird diese Iteration
anhält und die Bedingung nicht neu ausgewertet wird, sodass der Interpreter weitermachen kann:
let iterationCount = 1;
while( iterationCount <= 5 ) {
if( iterationCount === 3 ) {
console.log(`Iteration skipped.``);`
break;
}
console.log( `Loop ${ iterationCount }.` );
iterationCount++;
}
console.log( "Loop ended." );
> "Loop 1."
> "Loop 2."
> "Iteration skipped.
> "Loop ended."
Sie können while
verwenden, um eine bestimmte Anzahl von Durchläufen zu iterieren, wie in den
Beispiel aus dem vorherigen Beispiel. Der häufigste Anwendungsfall für while
ist jedoch eine Schleife
Unbestimmte Länge:
let randomize = () => Math.floor( Math.random() * 10 );
let randomNum = randomize();
while( randomNum !== 3 ){
console.log( `The number is not ${ randomNum }.` );
randomNum = randomize();
}
console.log( `The correct number, ${ randomNum }, was found.` );
> "The number is not 0."
> "The number is not 6."
> "The number is not 1."
> "The number is not 8."
> "The correct number, 3, was found."
do
...while
do
...while
ist eine Variante der while
-Schleife, in der die Bedingung
Die Bewertung erfolgt am Ende jeder Iteration der Schleife. Das bedeutet, dass der
Hauptteil der Schleife wird immer mindestens einmal ausgeführt.
Um eine do
...while
-Schleife zu erstellen, verwenden Sie das Schlüsselwort do
, gefolgt von der Anweisung
(oder Blockanweisung)
die bei jeder Iteration der Schleife ausgeführt wird. Fügen Sie direkt nach dieser Anweisung
while
und Klammern mit der Bedingung, die ausgewertet werden soll. Wann?
diese Bedingung nicht mehr als true
ausgewertet wird, endet die Schleife.
let iterationCount = 1;
do {
console.log( `Loop ${ iterationCount }.` );
iterationCount++;
} while ( iterationCount < 3 );
> "Loop 1."
> "Loop 2."
> "Loop 3."
Wie bei einer while
-Schleife ist auch hier der häufigste Anwendungsfall für do
...while
eine Schleife mit
Unbestimmte Länge:
let randomNum;
do {
randomNum = ( () => Math.floor( Math.random() * 10 ) )();
console.log( `Is the number ${ randomNum }?` );
} while ( randomNum !== 3 );
console.log( `Yes, ${ randomNum } was the correct number.` );
> "Is the number 9?"
> "Is the number 2?"
> "Is the number 8?"
> "Is the number 2?"
> "Is the number 3?"
> "Yes, 3 was the correct number."
for
Verwenden Sie for
-Schleifen, um über eine bekannte Anzahl zu iterieren. In Legacy-Codebasen war dies
wird häufig zur Iteration über die Elemente in einem Array verwendet.
Um eine for
-Schleife zu erstellen, verwenden Sie das Schlüsselwort for
gefolgt von mehreren Klammern
die die folgenden drei Ausdrücke akzeptiert und durch
Semikolons:
- Ein Ausdruck, der ausgewertet wird, wenn die Schleife beginnt
- Eine Bedingung, die bestimmt, ob die Schleife fortgesetzt werden soll
- Ein Ausdruck, der am Ende jeder Schleife ausgeführt werden soll
Fügen Sie nach diesen Klammern die Anweisung (normalerweise ein blockstatement) wird in die während der Schleife ausgeführt werden.
for( let i = 0; i < 3; i++ ) {
console.log( "This loop will run three times.")
}
Der erste Ausdruck initialisiert eine Variable, die als Zähler fungiert. Dieses
Ausdruck wird einmal vor der ersten Iteration der Schleife ausgewertet. Sie können
Initialisieren Sie diese Variable mit let
(oder bisher var
) wie jede andere
und ihr Umfang ist der Textkörper der Schleife. Diese Variablen können beliebige
eine gültige Kennung, wird aber häufig als i
für "Iteration" bezeichnet oder „Index“.
Dies scheint den etablierten
Best Practices für vorhersehbare ID-Namen
aber die Konvention ist so gut etabliert, dass sie auch für andere Entwickler auf der
auf einen Blick. Da indexierte Sammlungen auf null gesetzt werden,
haben diese Variablen fast immer einen Anfangswert von 0
.
Wie bei anderen Schleifenformen ist die Bedingung ein Ausdruck, der bestimmt,
ob die Schleife ausgeführt werden soll. Dies wird meistens verwendet, um eine Obergrenze
an den Iterationszähler gebunden. Der Interpreter wertet die Bedingung vor
die for
-Schleife zum ersten Mal ausführen.Wenn die Bedingung anfänglich nicht
als true
ausgewertet wird, wird der Textkörper der Schleife nicht ausgeführt.
Der letzte Ausdruck wird am Ende jeder Iteration über die Schleife ausgeführt. Sie wird normalerweise verwendet, um die ID um eins zu erhöhen.
for
-Schleifen iterieren in älteren Versionen am häufigsten durch Arrays.
Codebasen. In diesen Fällen ist die für die Fortsetzung der Schleife angegebene Bedingung eine
Die Iterationsanzahl ist kleiner oder gleich der Länge des Arrays, das iteriert wird
durch. Die zum Verfolgen der aktuellen Iterationsanzahl verwendete Variable dient
Wert erhöhen, der mit diesem Index im Array verknüpft ist, sodass jedes Element
Das Array, auf das reagiert werden soll:
var myArray = [ true, false, true ];
for( let i = 0; i <= myArray.length; i++ ) {
console.log( myArray[ i ] );
}
> true
> false
> true
Dieser Ansatz wird nicht mehr verwendet und durch modernere Ansätze zur iterierbare Datenstrukturen durchlaufen.
for
[...] of
[...]
Verwenden Sie for
...of
...-Schleifen, um über die Werte zu iterieren, die in einem
iterable Datenstruktur, z. B. ein Array, ein Satz oder eine Zuordnung.
In einer for
...of
...-Schleife wird das Schlüsselwort for
gefolgt von einem Satz Klammern verwendet.
die eine Variable enthält, gefolgt von of
, und dann der iterierten Datenstruktur.
vorbei. Die Variable kann eine Deklaration sein, die hier mit let
, const
oder
var
, eine zuvor im aktuellen Bereich deklarierte Variable, ein Objekt
oder eine Instanz von
desstrukturierenden Auftrags.
Sie enthält den Wert des Elements, das der aktuellen Iteration entspricht
aus der Schleife.
const myIterable = [ true, false, true ];
for( const myElement of myIterable ) {
console.log( myElement );
}
> true
> false
> true
In diesem Beispiel funktioniert die Verwendung von const
für myElement
, obwohl myElement
in jeder Iteration der Schleife
einen neuen Wert erhalten. Das liegt daran, dass Variablen
die mit let
oder const
deklariert sind, auf die Blockanweisung im
Schleife Die Variable wird zu Beginn jeder Iteration initialisiert und bei
das Ende dieser Iteration.
for
...in
...
Verwenden Sie for
...in
...-Schleifen, um über die aufzählbaren Eigenschaften eines Objekts zu iterieren.
einschließlich aufzählbarer übernommener Eigenschaften. Wie bei der Schleife for
...of
... wird mit
In der Schleife for
...in
... wird das Schlüsselwort for
gefolgt von einem Klammernpaar verwendet
die eine Variable enthält, die den Wert des Eigenschaftsschlüssels enthält, der dem
mit der aktuellen Iteration der Schleife. Auf diese Variable folgt der Parameter
in
und dann das Objekt, über das iteriert wird:
const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
console.log( myKey );
}
> "myProperty"
> "mySecondProperty"
Auch wenn sich der Wert von myKey
mit jeder Iteration der Schleife ändert,
können Sie const
ohne Fehler verwenden, da die Variable effektiv verworfen wird.
am Ende jeder Iteration und dann zu Beginn neu erstellt.
Der mit jedem Attributschlüssel verknüpfte Wert ist für den Nutzer nicht direkt verfügbar
for
...in
...-Syntax. Da die Schleife Zugriff auf einen Eigenschaftsschlüssel hat,
können Sie mit diesem Schlüssel „nachschlagen“, sein Wert:
const myObject = { "myProperty" : true, "mySecondProperty" : false };
for( const myKey in myObject ) {
const myValue = myObject[ myKey ];
console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "mySecondProperty : false"
Attribute, die von integrierten Konstruktoren übernommen werden, sind nicht aufzählbar, d. h.,
for
...in
... iteriert nicht durch Properties, die von Object
übernommen wurden
-Konstruktor. Alle aufzählbaren Eigenschaften im
Prototypenkette enthalten:
const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
myProperty: {
value: true,
enumerable: true
}
});
for ( const myKey in myObject ) {
const myValue = myObject[ myKey ];
console.log( `${ myKey } : ${ myValue }` );
}
> "myProperty : true"
> "protoProperty : true"
JavaScript bietet integrierte Methoden, mit denen bestimmt werden kann, ob eine Eigenschaft ein
direkte Eigenschaft des Objekts statt einer Eigenschaft des Prototyps des Objekts
Kette: Modern
Object.hasOwn()
und alte Object.prototype.hasOwnProperty()
-Methoden. Diese
evaluieren, ob eine bestimmte Eigenschaft vererbt (oder nicht deklariert) ist
Gibt true
nur für die unmittelbaren Eigenschaften eines angegebenen Objekts zurück:
const myPrototype = { "protoProperty" : true };
const myObject = Object.create( myPrototype, {
myProperty: {
value: true,
enumerable: true
}
});
for ( const myKey in myObject ) {
const myValue = myObject[ myKey ];
if ( Object.hasOwn( myObject, myKey ) ) {
console.log( `${ myKey } : ${ myValue }` );
}
}
> "myProperty : true"
Es gibt auch drei statische Methoden, die jeweils ein Array zurückgeben, das aus einem
Auflistbare Schlüssel (Object.keys()
), Werte (Object.values()
) oder
Schlüssel/Wert-Paare (Object.entries()
):
const myObject = { "myProperty" : true, "mySecondProperty" : false };
Object.keys( myObject );
> Array [ "myProperty", "mySecondProperty" ]
So können Sie Objektschlüssel, Werte oder Schlüssel/Wert-Paare (mithilfe von destruktiver Zuweisung) ohne Eigenschaften, die dem Prototyp dieses Objekts gehören:
const myPrototype = { "protoProperty" : "Non-enumerable property value." };
const myObject = Object.create( myPrototype, {
myProperty: {
value: "Enumerable property value.",
enumerable: true
}
});
for ( const propKey of Object.keys( myObject ) ) {
console.log( propKey );
}
> "myProperty"
for ( const propValue of Object.values( myObject ) ) {
console.log( propValue );
}
> "Enumerable property value."
for ( const [ propKey, propValue ] of Object.entries( myObject ) ) {
console.log( `${ propKey } : ${ propValue }` );
}
> "myProperty : Enumerable property value."
forEach()
Die forEach()
-Methoden, die vom Array bereitgestellt werden,
Karte, Set
NodeList-Konstruktoren sind eine nützliche Abkürzung für die Iteration über Daten,
im Kontext einer Rückruffunktion. Im Gegensatz zu anderen Schleifenformen
Schleife, die mit einer beliebigen forEach()
-Methode erstellt wurde, kann nicht unterbrochen werden mit break
oder
continue
forEach
ist eine Methode, die dem Prototyp jeder Datenstruktur gehört. Jeweils forEach
erwartet eine Callback-Funktion als Argument, auch wenn sie in Bezug auf
der Argumente enthalten,
die beim Aufruf der Funktion enthalten sind. Eine zweite, optionale
Argument gibt einen this
-Wert an, der als Aufrufkontext für die
Callback-Funktion verwendet werden.
Die mit Array.forEach
verwendete Callback-Funktion stellt Parameter bereit, die
den Wert des aktuellen Elements, den Index des aktuellen Elements und das Array, in dem die Methode forEach
aufgerufen wurde:
const myArray = [ true, false ];
myArray.forEach( ( myElement, i, originalArray ) => {
console.log( i, myElement, originalArray );
});
> 0 true Array(3) [ true, false ]
> 1 false Array(3) [ true, false ]
Die mit Map.forEach
verwendete Callback-Funktion stellt Parameter bereit, die die
Wert, der dem aktuellen Element zugeordnet ist, den Schlüssel, der dem aktuellen Element zugeordnet ist
und der Zuordnung, in der die forEach
-Methode aufgerufen wurde:
const myMap = new Map([
['myKey', true],
['mySecondKey', false ],
]);
myMap.forEach( ( myValue, myKey, originalMap ) => {
console.log( myValue, myKey, originalMap );
});
> true "myKey" Map { myKey → true, mySecondKey → false }
> false "mySecondKey" Map { myKey → true, mySecondKey → false }
Ein Set.forEach
-Callback enthält ähnliche Parameter. Da Set keine
oder Schlüssel, die sich von Werten unterscheiden, stellt das zweite Argument stattdessen ein
redundanten, ignorierbaren Wert, strikt auf Konsistenz der Syntax mit dem
andere forEach
-Methoden.
const mySet = new Set([ true, false ]);
mySet.forEach( ( myValue, myKey, originalSet ) => {
console.log( myValue, myKey, originalSet );
});
> true true Set [ true, false ]
> false false Set [ true, false ]
Iteratoren
Ein Iterable ist eine Datenstruktur, die aus einzelnen Elementen besteht,
mit den zuvor beschriebenen Ansätzen iteriert. Ein Iterator ist ein
iterierbares Objekt, das dem Iterator-Protokoll entspricht, das heißt, es muss
next()
-Methode, die nacheinander die darin enthaltenen Elemente durchläuft,
jedes Mal, wenn diese Methode aufgerufen wird, und gibt ein Objekt für jede sequenzielle
in einem bestimmten Format.
Die in JavaScript integrierten iterierbaren Datenstrukturen (z. B.
Array
Map und
Set) sind keine Iterationen in und
aber sie erben für alle eine iterator
-Methode, auf die über die
@@iterator
bekanntes Symbol,
gibt ein Iterator-Objekt zurück, das aus der iterierbaren Datenstruktur erstellt wurde:
const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();
myIterable;
> (3) [1, 2, 3]
myIterator;
> Array Iterator {}
Durch das Aufrufen der Methode next()
für einen Iterator werden die darin enthaltenen Elemente schrittweise durchlaufen.
enthält jeweils ein Objekt, wobei jeder Aufruf ein Objekt mit zwei
Eigenschaften: value
, die den Wert des aktuellen Elements enthalten, und
done
, ein boolescher Wert, der uns mitteilt, ob der Iterator das letzte Element in
der Datenstruktur. Der Wert von done
ist nur bei einem Aufruf von next()
true
führt zu dem Versuch, auf ein Element nach dem letzten Element im
-Iterator.
const myIterable = [ 1, 2, 3 ];
const myIterator = myIterable[ Symbol.iterator ]();
myIterator.next();
> Object { value: 1, done: false }
myIterator.next();
> Object { value: 2, done: false }
myIterator.next();
> Object { value: 3, done: false }
myIterator.next();
> Object { value: undefined, done: true }
Generatorfunktionen
Verwenden Sie das Schlüsselwort function*
(beachten Sie das Sternchen), um einen Generator zu deklarieren
-Funktion verwenden oder einen Generatorfunktionsausdruck definieren:
function* myGeneratorFunction() { };
Wie iteratoren behalten auch Generatorfunktionen den Status bei. Durch Aufrufen einer Generatorfunktion gibt ein neues Generator-Objekt zurück, gibt jedoch nicht sofort den Code im Hauptteil der Funktion ausführen:
function* myGeneratorFunction() {
console.log( "Generator function body ")
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject;
> Generator { }
typeof myGeneratorObject;
> "object"
Generator-Objekte folgen dem Iterator-Protokoll. Der Wert, den jeder Aufruf
next()
für die Rückgabe einer Generatorfunktion wird durch einen yield
-Ausdruck bestimmt.
die die Ausführung der Generatorfunktion anhält und den Wert der Funktion
Ausdruck, der das yield
-Keyword enthält. Spätere Aufrufe an next()
Ausführung der Funktion fortsetzen, beim nächsten yield
-Ausdruck anhalten und
und gibt den zugehörigen Wert zurück.
function* myGeneratorFunction() {
yield "My first yielded value.";
yield "My second yielded value.";
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: "My first yielded value.", done: false }
myGeneratorObject.next();
> Object { value: "My second yielded value.", done: false }
Wenn next()
aufgerufen wird, nachdem keine weiteren Werte mit yield
angegeben wurden,
return
oder throw
(im Falle eines Fehlers), der Rest der Funktion
Text ausgeführt wird und das zurückgegebene Objekt den value
-Wert undefined
und den done
-Wert hat
Eigenschaft von true
:
function* myGeneratorFunction() {
console.log( "Start of the generator function." );
yield "First";
console.log( "Second part of the generator function." );
yield "Second";
console.log( "Third part of the generator function." );
yield "Third";
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> "Start of the generator function."
> Object { value: "First", done: false }
myGeneratorObject.next();
> "Second part of the generator function."
> Object { value: "Second", done: false }
myGeneratorObject.next();
> "Third part of the generator function."
> Object { value: "Third", done: false }
myGeneratorObject.next();
> Object { value: undefined, done: true }
Verwenden Sie next()
nur für das Objekt, das die Generatorfunktion zurückgibt, nicht für das
Generatorfunktion selbst. Andernfalls führt jeder Aufruf der Generatorfunktion
Erstellt ein neues Generatorobjekt:
function* myGeneratorFunction() {
yield "First";
yield "Second";
};
myGeneratorFunction().next();
> Object { value: "First", done: false }
myGeneratorFunction().next();
> Object { value: "First", done: false }
Wie bei jeder Funktion wird die Generatorfunktion angehalten, wenn sie auf ein return
-Objekt stößt.
Keyword. Anschließend wird ein Objekt an den aufrufenden Kontext zurückgegeben, das die
zurückgegebener Wert und eine done
-Eigenschaft mit dem Wert true
.
function* myGeneratorFunction() {
yield 1;
yield 2;
return 3;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next().done;
> Object { value: 1, done: false }
myGeneratorObject.next().done;
> Object { value: 2, done: false }
myGeneratorObject.next();
> Object { value: 3, done: true }
Ein yield
-Ausdruck kann einen Teil der Semantik einer Kennung übernehmen,
sodass eine wechselseitige "Kommunikation" und zurück zum gesperrten Teil
Generatorfunktion erzeugen. Wenn ein Wert als next()
-Methode eines Generators übergeben wird:
ein Argument enthält, ersetzt es den Wert, der mit dem vorherigen, gesperrten
yield
-Ausdruck:
function* myGeneratorFunction() {
const firstYield = yield;
yield firstYield + 10;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: undefined, done: false }
myGeneratorObject.next( 5 );
> Object { value: 15, done: false }
Beachten Sie, dass dabei der gesamte Ausdruck ersetzt wird, der mit dem
vorherigen yield
und weist nicht nur den Wert der vorherigen yield
den in next()
angegebenen Wert:
function* myGeneratorFunction() {
const firstYield = yield;
const secondYield = yield firstYield + 100;
yield secondYield + 10;
};
const myGeneratorObject = myGeneratorFunction();
myGeneratorObject.next();
> Object { value: undefined, done: false }
myGeneratorObject.next( 10 ); // Can be thought of as changing the value of the `firstYield` variable to `10
> Object { value: 110, done: false }
myGeneratorObject.next( 20 ); // Can be thought of as changing the value of the `secondYield` variable to `20`, _not_ `20 + 100;`
> Object { value: 30, done: false }
Alle Argumente, die an den ersten Aufruf von next()
übergeben werden, werden ignoriert, da es
vorherigen yield
-Ausdruck, um diesen Wert zu akzeptieren. Wie bei jeder anderen Funktion
Argumente, die an den ersten Aufruf der Generatorfunktion übergeben werden, sind im gesamten
Umfang des Hauptteils der Generatorfunktion:
function* myGeneratorFunction( startingValue ) {
let newValue = yield startingValue + 1;
newValue = yield newValue + 10;
yield startingValue + 20;
};
const myGeneratorObject = myGeneratorFunction( 2 );
myGeneratorObject.next( 1 );
> Object { value: 3, done: false }
myGeneratorObject.next( 5 );
> Object { value: 15, done: false }
myGeneratorObject.next( 10 );
Object { value: 22, done: false }
Der Operator yield*
(beachten Sie das Sternchen) wird mit einem iterierbaren Wert verwendet, z. B.
eine weitere Generatorfunktion, um über jeden Wert zu iterieren und seinen Operanden zu erhalten.
gibt Folgendes zurück:
function* mySecondaryGenerator() {
yield 2;
yield 3;
}
function* myGenerator() {
yield 1;
yield* mySecondaryGenerator();
yield 4;
return 5;
}
const myIterator = myGenerator();
myIterator.next();
> Object { value: 1, done: false }
myIterator.next();
> Object { value: 2, done: false }
myIterator.next();
> Object { value: 3, done: false }
myIterator.next();
> Object { value: 4, done: false }
myIterator.next();
> Object { value: 5, done: true }
Asynchrones JavaScript
Obwohl JavaScript grundsätzlich synchron ist, gibt es Mechanismen, die es den Entwicklern ermöglichen, die Ereignisschleife, asynchrone Aufgaben.
Promise-Objekte
Ein Promise ist ein Platzhalter für einen Wert, der nicht bekannt ist, wenn das Versprechen erstellt. Es ist ein Container, der einen asynchronen Vorgang vorgibt, die Begriffe der der als Erfolg oder Misserfolg gilt, die auszuführenden Aktionen und dem sich daraus ergebenden Wert.
Promise-Instanz mit dem Operator new
und dem integrierten Promise
erstellen
-Konstruktor. Dieser Konstruktor akzeptiert die Funktion Executor
als Argument verwenden. Diese Executor-Funktion wird in der Regel dazu verwendet, eine oder mehrere
asynchrone Aktionen ein und geben dann die Begriffe vor, nach denen das Promise
als erfolgreich erfüllt oder abgelehnt gelten. Ein Promise wird als ausstehend definiert.
während die Executor-Funktion ausgeführt wird. Nach Abschluss des Executors
als erfüllt (oder in einigen Dokumentationsquellen behoben) gilt, wenn
die Executor-Funktion und die auszuführende asynchrone Aktion abgeschlossen sind.
erfolgreich und abgelehnt, wenn bei der Executor-Funktion ein Fehler auftritt
die asynchrone Aktion schlägt fehl. Nachdem ein Versprechen erfüllt oder
abgelehnt wurde, gilt der Betrag als beseitigt.
const myPromise = new Promise( () => { });
Der Konstruktor ruft die Executor-Funktion mit zwei Argumenten auf. Diese Argumente sind Funktionen, mit denen Sie das Versprechen manuell erfüllen oder ablehnen können:
const myPromise = new Promise( ( fulfill, reject ) => { });
Die Funktionen, die zur Erfüllung oder Ablehnung eines Versprechens verwendet werden, werden mit dem resultierenden des Promise als Argument (normalerweise ein Fehler bei einer Ablehnung):
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = true;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was successful." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 10000);
});
myPromise;
> Promise { <state>: "pending" }
myPromise;
> Promise { <state>: "fulfilled", <value>: "This Promise was successful." }
Verkettung von Wertversprechen
Das resultierende Promise-Objekt kann mithilfe von then()
, catch()
und
finally()
-Methoden, die vom Promise-Konstruktor übernommen wurden. Jede dieser Optionen
-Methoden gibt ein Promise zurück, auf das sofort mit then()
,
catch()
oder finally()
, sodass Sie die resultierenden Promise-Objekte verketten.
then()
bietet zwei Callback-Funktionen als Argumente. Verwenden Sie die erste
das sich daraus ergebende Versprechen
und das zweite Versprechen abzulehnen. Beide Methoden akzeptieren einen
, das dem resultierenden Promise seinen Wert zurückgibt.
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = true;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was fulfilled." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 100);
});
myPromise.then( successfulResult => console.log( successfulResult ), failedResult => console.error( failedResult ) );
> "This Promise was successful."
Sie können auch then()
verwenden, um nur den erfüllten Status zu verarbeiten, und catch
, um
den Status „Abgelehnt“ bearbeiten. Rufen Sie catch
mit einem einzelnen Argument auf, das den Parameter
Wert, der in der Ablehnungsmethode des Promise angegeben wurde:
const myPromise = new Promise( ( fulfill, reject ) => {
const myResult = false;
setTimeout(() => {
if( myResult === true ) {
fulfill( "This Promise was fulfilled." );
} else {
reject( new Error( "This Promise has been rejected." ) );
}
}, 100);
});
myPromise
.then( fulfilledResult => console.log(fulfilledResult ) )
.catch( rejectedResult => console.log( rejectedResult ) )
.finally( () => console.log( "The Promise has settled." ) );
> "Error: This Promise has been rejected."
> "The Promise has settled."
Im Gegensatz zu then
und catch
, mit denen eine Handler-Funktion ausgeführt werden kann, wenn ein Promise-Objekt
erfüllt oder abgelehnt wurde, wird eine Funktion als Argument an finally
übergeben.
wird unabhängig davon aufgerufen, ob das Promise erfüllt oder abgelehnt wurde.
Die Handler-Funktion wird ohne Argumente aufgerufen, da sie nicht dazu gedacht ist,
mit den vom Promise übergebenen Werten arbeiten, nur um Code nach der
Das Versprechen ist vollständig.
Gleichzeitigkeit
Der Promise-Konstruktor bietet vier Methoden für die Arbeit mit mehreren verwandten
Promise-Objekte mithilfe eines iterables, das Promise-Objekte enthält. Diese
Jede Methode gibt ein Versprechen zurück, das je nach Bundesstaat erfüllt oder abgelehnt wird.
der an sie übergebenen Promise-Objekte. Mit Promise.all()
wird beispielsweise ein Promise erstellt.
die nur erfüllt wird, wenn jedes an diese Methode übergebene Versprechen erfüllt wird:
const firstPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const secondPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const thirdPromise = new Promise( ( fulfill, reject ) => fulfill( "Successful. ") );
const failedPromise = new Promise( ( fulfill, reject ) => reject( "Failed.") );
const successfulPromises = [ firstPromise, secondPromise, thirdPromise ];
const oneFailedPromise = [ failedPromise, ...successfulPromises ];
Promise.all( successfulPromises )
.then( ( allValues ) => {
console.log( allValues );
})
.catch( ( failValue ) => {
console.error( failValue );
});
> Array(3) [ "Successful. ", "Successful. ", "Successful. " ]
Promise.all( oneFailedPromise )
.then( ( allValues ) => {
console.log( allValues );
})
.catch( ( failValue ) => {
console.error( failValue );
});
> "Failed."
Die Promise-Methoden für die Gleichzeitigkeit sind folgende:
Promise.all()
- Wird nur dann erfüllt, wenn alle angegebenen Promises erfüllt sind.
Promise.any()
- Erfüllt, wenn eines der angegebenen Promises erfüllt, aber nur abgelehnt wird wenn alle Promise-Objekte abgelehnt werden.
Promise.allSettled()
- Wird erfüllt, wenn sich Versprechen entschieden haben, unabhängig von ihrem Ergebnis.
Promise.race()
- Aufgrund des Ergebnisses des ersten Zahlungsversprechens abgelehnt oder erfüllt und ignoriert alle Promise-Objekte, die später geklärt wurden.
async
/await
Wenn Sie das Schlüsselwort async
vor einer Funktionsdeklaration verwenden
oder Funktionsausdruck, einen beliebigen
Wert, den die Funktion zurückgibt, als erfülltes Promise zurückgegeben wird, das Folgendes enthält:
Wert. So können Sie asynchrone Vorgänge mit denselben
Workflows als synchrone Entwicklung.
async function myFunction() {
return "This is my returned value.";
}
myFunction().then( myReturnedValue => console.log( myReturnedValue ) );
> "This is my returned value."
Der Ausdruck await
pausiert die Ausführung einer asynchronen Funktion, während
das zugehörige Versprechen abgewickelt ist. Nach der Erfüllung des Versprechens
Der Ausdruck await
ist der erfüllte oder abgelehnte Wert des Versprechens.
async function myFunction() {
const myPromise = new Promise( ( fulfill, reject ) => { setTimeout( () => fulfill( "Successful. "), 5000 ); });
const myPromisedResult = await myPromise;
return myPromisedResult;
}
myFunction()
.then( myResult => console.log( myResult ) )
.catch( myFailedResult => console.error( myFailedResult ) );
> "Successful."
Alle in einem await
-Ausdruck enthaltenen Nicht-Promise-Werte werden als
Versprechen:
async function myFunction() {
const myPromisedResult = await "String value.";
return myPromisedResult;
}
myFunction()
.then( myResult => console.log( myResult ) )
.catch( myFailedResult => console.error( myFailedResult ) );
> "String value."
Wissen testen
Welche Art von Schleife verwenden Sie, um über eine bekannte Menge zu iterieren?
for
do...while
while