034.3 Lektion 1
Zertifikat: |
Web Development Essentials |
---|---|
Version: |
1.0 |
Thema: |
034 JavaScript-Programmierung |
Lernziel: |
034.3 JavaScript-Kontrollstrukturen und -Funktionen |
Lektion: |
1 von 2 |
Einführung
Wie jede andere Programmiersprache ist auch JavaScript-Code eine Sammlung von Anweisungen, die einem Befehlsinterpreter mitteilen, was er nacheinander tun soll. Das bedeutet jedoch nicht, dass jede Anweisung nur einmal oder überhaupt ausgeführt wird. Die meisten Anweisungen sollen nur ausgeführt werden, wenn bestimmte Bedingungen erfüllt sind. Selbst wenn ein Skript asynchron durch unabhängige Ereignisse ausgelöst wird, muss es oft eine Reihe von Kontrollvariablen überprüfen, um den richtigen Teil des Codes zur Ausführung zu finden.
If-Anweisungen
Die einfachste Kontrollstruktur bietet die if
-Anweisung, die die unmittelbar folgende Anweisung ausführt, wenn die angegebene Bedingung wahr ist. JavaScript betrachtet Bedingungen als wahr, wenn der ermittelte Wert ungleich Null ist. Alles, was innerhalb der Klammer nach dem Wort if
steht (Leerzeichen werden ignoriert), wird als Bedingung interpretiert. Im folgenden Beispiel ist die Zahl 1
die Bedingung:
if ( 1 ) console.log("1 is always true");
Die Zahl 1
wird in dieser Beispielbedingung explizit angegeben, so dass sie als konstanter Wert behandelt wird (sie bleibt während der gesamten Ausführung des Skripts gleich) und bei Verwendung als bedingter Ausdruck immer true
ergibt. Wir könnten auch das Wort true
(ohne die Anführungszeichen) anstelle von 1
verwenden, da es von der Sprache ebenfalls als ein wahrer Wert behandelt wird. Die Anweisung console.log
gibt ihre Argumente im Konsolenfenster des Browsers aus.
Tip
|
Die Browserkonsole zeigt Fehler, Warnungen und Informationsmeldungen an, die mit der JavaScript-Anweisung |
Obwohl syntaktisch korrekt, sind konstante Ausdrücke in Bedingungen nicht sehr nützlich. In einer tatsächlichen Anwendung werden Sie wahrscheinlich den Wahrheitsgehalt einer Variablen testen wollen:
let my_number = 3;
if ( my_number ) console.log("The value of my_number is", my_number, "and it yields true");
Der der Variablen my_number
zugewiesene Wert (3
) ist ungleich Null, ergibt also true. Dieses Beispiel ist jedoch nicht gebräuchlich, da man selten testen muss, ob eine Zahl gleich Null ist. Viel üblicher ist es, einen Wert mit einem anderen zu vergleichen und zu prüfen, ob das Ergebnis wahr ist:
let my_number = 3;
if ( my_number == 3 ) console.log("The value of my_number is", my_number, "indeed");
Der doppelte Vergleichsoperator wird verwendet, weil der einfache Gleichheitsoperator bereits als Zuweisungsoperator definiert ist. Der Wert auf jeder Seite des Operators wird als Operand bezeichnet. Die Reihenfolge der Operanden spielt keine Rolle, und jeder Ausdruck, der einen Wert liefert, kann ein Operand sein. Hier eine Liste der anderen verfügbaren Vergleichsoperatoren:
value1 == value2
-
wahr falls
value1
ist gleichvalue2
. value1 != value2
-
wahr falls
value1
ist nicht gleichvalue2
. value1 < value2
-
wahr falls
value1
ist kleiner alsvalue2
. value1 > value2
-
wahr falls
value1
ist größer alsvalue2
. value1 ⇐ value2
-
wahr falls
value1
ist kleiner als oder gleichvalue2
. value1 >= value2
-
wahr falls
value1
ist größer als oder gleichvalue2
.
Normalerweise spielt es keine Rolle, ob der Operand links vom Operator eine Zeichenkette und der Operand rechts eine Zahl ist, solange JavaScript den Ausdruck in einen sinnvollen Vergleich umwandeln kann. So wird eine Zeichenkette, die das Zeichen 1
enthält, beim Vergleich mit einer Zahlenvariablen als die Zahl 1 behandelt. Um sicherzustellen, dass der Ausdruck nur dann wahr ist, wenn beide Operanden denselben Typ und Wert haben, nutzen Sie den strikten Identitätsoperator ===
anstelle von ==
. Ebenso wird der strikte Nicht-Identitätsoperator !==
als wahr ausgewertet, wenn der erste Operand nicht denselben Typ und Wert wie der zweite Operator hat.
Optional führt die if
-Kontrollstruktur eine alternative Anweisung aus, wenn der Ausdruck als falsch bewertet wird:
let my_number = 4;
if ( my_number == 3 ) console.log("The value of my_number is 3");
else console.log("The value of my_number is not 3");
Die else
-Anweisung sollte unmittelbar auf die if
-Anweisung folgen. Bis jetzt haben wir nur eine Anweisung ausgeführt, wenn die Bedingung erfüllt ist. Um mehr als eine Anweisung auszuführen, müssen Sie sie in geschweifte Klammern einschließen:
let my_number = 4;
if ( my_number == 3 )
{
console.log("The value of my_number is 3");
console.log("and this is the second statement in the block");
}
else
{
console.log("The value of my_number is not 3");
console.log("and this is the second statement in the block");
}
Eine Gruppe von einer oder mehreren Anweisungen, die durch ein Paar geschweifte Klammern begrenzt sind, wird als Blockanweisung (Block Statement) bezeichnet. Es ist üblich, Blockanweisungen auch dann zu verwenden, wenn nur eine einzige Anweisung auszuführen ist, um den Kodierungsstil im gesamten Skript einheitlich zu gestalten. Außerdem müssen in JavaScript weder die geschweiften Klammern noch die Anweisungen in getrennten Zeilen stehen, was jedoch die Lesbarkeit verbessert und die Wartung des Codes erleichtert.
Sie können Kontrollstrukturen ineinander verschachteln, aber es ist wichtig, die öffnenden und schließenden Klammern der einzelnen Blockanweisungen nicht zu verwechseln:
let my_number = 4;
if ( my_number > 0 )
{
console.log("The value of my_number is positive");
if ( my_number % 2 == 0 )
{
console.log("and it is an even number");
}
else
{
console.log("and it is an odd number");
}
} // end of if ( my_number > 0 )
else
{
console.log("The value of my_number is less than or equal to 0");
console.log("and I decided to ignore it");
}
Die Ausdrücke, die die if
-Anweisung auswertet, können komplizierter sein als einfache Vergleiche. Dies ist im vorigen Beispiel der Fall, in dem der arithmetische Ausdruck my_number % 2
innerhalb der Klammern im verschachtelten if
verwendet wurde. Der %
-Operator gibt den Rest zurück, nachdem er die Zahl auf der linken Seite durch die Zahl auf der rechten Seite geteilt hat. Arithmetische Operatoren wie %
haben Vorrang vor Vergleichsoperatoren wie ==
, so dass der Vergleich das Ergebnis des arithmetischen Ausdrucks als seinen linken Operanden verwendet.
In vielen Situationen lassen sich verschachtelte bedingte Strukturen mit Hilfe von logischen Operatoren zu einer einzigen Struktur zusammenfassen. Wären wir beispielsweise nur an positiven geraden Zahlen interessiert, könnte wir eine einzige if
-Struktur verwenden:
let my_number = 4;
if ( my_number > 0 && my_number % 2 == 0 )
{
console.log("The value of my_number is positive");
console.log("and it is an even number");
}
else
{
console.log("The value of my_number either 0, negative");
console.log("or it is a negative number");
}
Das doppelte kaufmännische Und als Operator &&
im ausgewerteten Ausdruck ist der logische AND-Operator. Er wird nur dann als wahr gewertet, wenn der Ausdruck links und der Ausdruck rechts wahr sind. Wenn Sie Zahlen ermitteln, die entweder positiv oder gerade sind, sollten Sie stattdessen den Operator ||
verwenden, der für den logischen Operator OR (Oder) steht:
let my_number = -4;
if ( my_number > 0 || my_number % 2 == 0 )
{
console.log("The value of my_number is positive");
console.log("or it is a even negative number");
}
In diesem Beispiel erfüllen nur negative ungerade Zahlen die Kriterien des zusammengesetzten Ausdrucks nicht. Um das Gegenteil zu erzielen, d.h. nur negative ungerade Zahlen zu ermitteln, ergänzen Sie den logischen NOT-Operator !
am Anfang des Ausdrucks:
let my_number = -5;
if ( ! ( my_number > 0 || my_number % 2 == 0 ) )
{
console.log("The value of my_number is an odd negative number");
}
Die Klammern im zusammengesetzten Ausdruck bewirken, dass der eingeschlossene Ausdruck zuerst ausgewertet wird. Ohne diese Klammern würde der NOT-Operator nur auf my_number > 0
angewandt und erst dann der OR-Ausdruck ausgewertet. Die Operatoren &&
und ||
werden auch als binäre logische Operatoren bezeichnet, da sie zwei Operanden benötigen. !
ist hingegen ein unärer logischer Operator, der nur einen Operanden benötigt.
Switch-Strukturen
Obwohl die if
-Struktur recht vielseitig ist und ausreicht, um den Programmablauf zu steuern, ist die switch
-Kontrollstruktur möglicherweise besser geeignet, wenn andere Ergebnisse als wahr oder falsch ausgewertet werden müssen. Um zum Beispiel für jedes aus einer Liste ausgewählte Element eine bestimmte Aktion durchzuführen, müssen wir für jede Bewertung eine if
-Struktur schreiben:
// Available languages: en (English), es (Spanish), pt (Portuguese)
let language = "pt";
// Variable to register whether the language was found in the list
let found = 0;
if ( language == "en" )
{
found = 1;
console.log("English");
}
if ( found == 0 && language == "es" )
{
found = 1;
console.log("Spanish");
}
if ( found == 0 && language == "pt" )
{
found = 1;
console.log("Portuguese");
}
if ( found == 0 )
{
console.log(language, " is unknown to me");
}
In diesem Beispiel wird eine Hilfsvariable found
von allen if
-Strukturen verwendet, um herauszufinden, ob eine Übereinstimmung vorliegt. In einem Fall wie diesem erfüllt die Struktur switch
eben diese Aufgabe, allerdings deutlich prägnanter:
switch ( language )
{
case "en":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
console.log("Portuguese");
break;
default:
console.log(language, " not found");
}
Jedes verschachtelte case
wird als Klausel (Clause) bezeichnet. Wenn eine Klausel mit dem ausgewerteten Ausdruck übereinstimmt, führt sie die Anweisungen nach dem Doppelpunkt bis zur break
-Anweisung aus. Die letzte Klausel benötigt keine break
-Anweisung und wird oft verwendet, um die Standardaktion zu definieren, wenn es keine weiteren Übereinstimmungen gibt. Wie im Beispiel zu sehen, wird die Hilfsvariable in der Struktur switch
nicht benötigt.
Warning
|
|
Wenn mehr als eine Klausel dieselbe Aktion auslöst, können Sie zwei oder mehr case
-Bedingungen kombinieren:
switch ( language )
{
case "en":
case "en_US":
case "en_GB":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
case "pt_BR":
console.log("Portuguese");
break;
default:
console.log(language, " not found");
}
Schleifen
In den vorangegangenen Beispielen waren die if
- und switch
-Strukturen gut geeignet für Aufgaben, die nur einmal ausgeführt werden müssen, nachdem sie einen oder mehrere bedingte Tests bestanden haben. Es gibt jedoch Situationen, in denen eine Aufgabe wiederholt ausgeführt werden muss – in einer so genannten Schleife (Loop) –, solange ihr bedingter Ausdruck weiterhin als wahr getestet wird. Wenn Sie beispielsweise wissen wollen, ob eine Zahl eine Primzahl ist, müssen Sie prüfen, ob die Division dieser Zahl durch eine beliebige ganze Zahl, die größer als 1 und kleiner als sie selbst ist, einen Rest von 0 ergibt. Wenn dies der Fall ist, hat die Zahl einen ganzzahligen Faktor und ist nicht prim. (Dies ist keine strenge oder effiziente Methode, um Primzahlen zu finden, aber sie funktioniert als einfaches Beispiel.) Für solche Fälle sind Schleifenstrukturen besser geeignet, insbesondere die Anweisung while
:
// A naive prime number tester
// The number we want to evaluate
let candidate = 231;
// Auxiliary variable
let is_prime = true;
// The first factor to try
let factor = 2;
// Execute the block statement if factor is
// less than candidate and keep doing it
// while factor is less than candidate
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next factor to try. Simply
// increment the current factor by one
factor++;
}
// Display the result in the console window.
// If candidate has no integer factor, then
// the auxiliary variable is_prime still true
if ( is_prime )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
Die Blockanweisung, die auf die Anweisung while
folgt, wird wiederholt, solange die Bedingung factor < candidate
wahr ist. Sie wird mindestens einmal ausgeführt, solange wir die Variable factor
mit einem Wert kleiner als candidate
initialisieren. Die if
-Struktur, die in die while
-Struktur eingebettet ist, prüft, ob der Rest von candidate
geteilt durch factor
Null ist. Wenn ja, ist die Kandidaten-Zahl nicht prim und die Schleife kann beendet werden. Die Anweisung break
beendet die Schleife, und die Ausführung springt zur ersten Anweisung nach dem while
-Block.
Beachten Sie, dass sich das Ergebnis der Bedingung, die von der`while`-Anweisung verwendet wird, bei jeder Schleife ändern muss, andernfalls würde die Blockanweisung “ewig” laufen. Im Beispiel erhöhen wir die Variable factor
— der nächste Divisor, den wir ausprobieren wollen — und das garantiert, dass die Schleife irgendwann endet.
Diese einfache Implementierung eines Primzahlprüfers funktioniert wie erwartet. Wir wissen jedoch, dass eine Zahl, die nicht durch zwei teilbar ist, auch nicht durch eine andere gerade Zahl teilbar ist. Daher könnten wir die geraden Zahlen einfach auslassen, indem wir eine weitere if
-Anweisung hinzufügen:
while ( factor < candidate )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
factor++;
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
// The next number that will divide the candidate
factor++;
}
Die Anweisung continue
ist ähnlich der Anweisung break
, aber statt diese Iteration der Schleife zu beenden, wird der Rest des Schleifenblocks ignoriert und eine neue Iteration begonnen. Beachten Sie, dass die Variable factor
vor der continue
-Anweisung geändert wurde, sonst hätte die Schleife bei der nächsten Iteration wieder dasselbe Ergebnis. Dieses Beispiel ist zu einfach und das Überspringen eines Teils der Schleife wird die Performance nicht wirklich verbessern, aber das Überspringen überflüssiger Anweisungen ist sehr wichtig, wenn man effiziente Anwendungen schreibt.
Schleifen werden so häufig genutzt, dass es sie in vielen Varianten gibt. Die for
-Schleife ist besonders geeignet, um durch aufeinanderfolgende Werte zu iterieren, da sie es ermöglicht, die Schleifenregeln in einer einzigen Zeile zu definieren:
for ( let factor = 2; factor < candidate; factor++ )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
}
Dieses Beispiel liefert dasselbe Ergebnis wie das vorherige while
-Beispiel, aber der Klammerausdruck enthält drei Teile, die durch Semikola getrennt sind: die Initialisierung (let factor = 2
), die Schleifenbedingung (factor < candidate
) und den abschließenden Ausdruck, der am Ende jeder Schleifeniteration ausgewertet wird (factor+`). Die Anweisungen `continue` und `break` gelten auch für `for`-Schleifen. Der abschließende Ausdruck in Klammern (`factor+
) wird nach der Anweisung continue
ausgewertet, sollte also nicht innerhalb der Blockanweisung stehen, da er sonst vor der nächsten Iteration zweimal inkrementiert wird.
JavaScript verfügt über spezielle for
-Schleifen, um mit Array-ähnlichen Objekten zu arbeiten. Wir könnten zum Beispiel ein Array von Kandidatenvariablen statt nur einer prüfen:
// A naive prime number tester
// The array of numbers we want to evaluate
let candidates = [111, 139, 293, 327];
// Evaluates every candidate in the array
for (candidate of candidates)
{
// Auxiliary variable
let is_prime = true;
for ( let factor = 2; factor < candidate; factor++ )
{
// Skip even factors bigger than two
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// The remainder is zero, so the candidate is not prime
is_prime = false;
break;
}
}
// Display the result in the console window
if ( is_prime )
{
console.log(candidate, "is prime");
}
else
{
console.log(candidate, "is not prime");
}
}
Die Anweisung for (candidate of candidates)
weist der Variablen candidates
ein Element aus dem Array candidate
zu und verwendet es in der Blockanweisung, wobei der Vorgang für jedes Element im Array wiederholt wird. Sie müssen candidate
nicht eigens deklarieren, da die for
-Schleife sie definiert. Schließlich wurde derselbe Code aus dem vorherigen Beispiel in diese neue Blockanweisung eingebettet, aber dieses Mal wird jeder Kandidat im Array getestet.
Geführte Übungen
-
Welche Werte der Variablen
my_var
erfüllen die Bedingungmy_var > 0 && my_var < 9
? -
Welche Werte der Variablen
my_var
erfüllen die Bedingungmy_var > 0 || my_var < 9
? -
Wie oft führt die folgende
while
-Schleife ihre Blockanweisung aus?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Offene Übungen
-
Was passiert, wenn Sie den Gleichheitszuweisungsoperator
=
anstelle des Gleichheitsvergleichsoperators==
verwenden? -
Schreiben Sie ein Codefragment unter Verwendung der
if
-Kontrollstruktur, bei dem ein gewöhnlicher Gleichheitsvergleich wahr ergibt, ein strenger Gleichheitsvergleich jedoch nicht. -
Schreiben Sie die folgende
for
-Anweisung um, indem Sie den unären logischen Operator NOT in der Schleifenbedingung verwenden. Das Ergebnis der Bedingung sollte dasselbe sein.for ( let factor = 2; factor < candidate; factor++ )
-
Schreiben Sie auf der Grundlage der Beispiele aus dieser Lektion eine Schleifensteuerungsstruktur, die alle ganzzahligen Faktoren einer bestimmten Zahl ausgibt.
Zusammenfassung
Diese Lektion behandelt Kontrollstrukturen in JavaScript-Code. Bedingte Strukturen und Schleifen sind wesentliche Elemente jedes Programmierparadigmas, und die Webentwicklung mit JavaScript bildet da keine Ausnahme. In dieser Lektion werden die folgenden Konzepte und Verfahren behandelt:
-
Die
if
-Anweisung und Vergleichsoperatoren. -
Wie man die
switch
-Struktur mitcase
,default
undbreak
verwendet. -
Der Unterschied zwischen gewöhnlichem und striktem Vergleich.
-
Kontrollstrukturen für Schleifen:`while` und
for
.
Lösungen zu den geführten Übungen
-
Welche Werte der Variablen
my_var
erfüllen die Bedingungmy_var > 0 && my_var < 9
?Nur Zahlen, die sowohl größer als 0 als auch kleiner als 9 sind. Der logische Operator
&&
(AND) erfordert, dass beide Vergleiche zutreffen. -
Welche Werte der Variablen
my_var
erfüllen die Bedingungmy_var > 0 || my_var < 9
?Mit dem logischen Operator
||
(OR) wird jede Zahl übereinstimmen, da jede Zahl entweder größer als 0 oder kleiner als 9 ist. -
Wie oft führt die folgende
while
-Schleife ihre Blockanweisung aus?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Die Blockanweisung wird unendlich oft wiederholt, da keine Stopp-Bedingung angegeben wurde.
Lösungen zu den offenen Übungen
-
Was passiert, wenn Sie den Gleichheitszuweisungsoperator
=
anstelle des Gleichheitsvergleichsoperators==
verwenden?Der Wert auf der rechten Seite des Operators wird der Variablen auf der linken Seite zugewiesen und das Ergebnis wird an den Vergleich übergeben, was nicht unbedingt das gewünschte Verhalten ist.
-
Schreiben Sie ein Codefragment unter Verwendung der
if
-Kontrollstruktur, bei dem ein gewöhnlicher Gleichheitsvergleich wahr ergibt, ein strenger Gleichheitsvergleich jedoch nicht.let a = "1"; let b = 1; if ( a == b ) { console.log("An ordinary comparison will match."); } if ( a === b ) { console.log("A strict comparison will not match."); }
-
Schreiben Sie die folgende
for
-Anweisung um, indem Sie den unären logischen Operator NOT in der Schleifenbedingung verwenden. Das Ergebnis der Bedingung sollte dasselbe sein.for ( let factor = 2; factor < candidate; factor++ )
Answer:
for ( let factor = 2; ! (factor >= candidate); factor++ )
-
Schreiben Sie auf der Grundlage der Beispiele aus dieser Lektion eine Schleifensteuerungsstruktur, die alle ganzzahligen Faktoren einer bestimmten Zahl ausgibt.
for ( let factor = 2; factor <= my_number; factor++ ) { if ( my_number % factor == 0 ) { console.log(factor, " is an integer factor of ", my_number); } }