Programmierkurs
für Naturwissenschaftler/innen

Scope

Was ist der Scope?

Mit einem Wort, es ist der gültige Bereich einer Variablen (usw.).

Ein kurzer Rückblick

Bis jetzt haben Sie gesehen, dass eine Variable von dem Ort, an dem sie in let deklariert (definiert) wurde, bis zum Ende verwendet werden kann. Mit anderen Worten, sie ist ab let gültig.

// test

let a = 10;

console.log(a);

Andererseits, wie wir in den Abschnitten Funktionen, Bedingte Verzweigung sowie Iteration gesehen haben, der von { und } eingeschlossene Bereich als Block bezeichnet.

Normalerweise würde man es nicht auf diese Weise schreiben, aber man kann auch einen einzelnen Block verwenden. Zur Erläuterung werden wir hier diese Schreibweise verwenden.

let i = 10;

console.log("before block: i =", i);

{
  // Block
}

console.log(" after block: i =", i);

Was wird das Ergebnis sein, wenn Sie das folgende Programm ausführen?

let i = 10;

console.log("before block: i =", i);

{
  console.log("    in block: i =", i);
}

console.log(" after block: i =", i);

Sagen Sie voraus, was Sie sehen werden, wenn Sie das obige Programm ausführen. Geben Sie dann das Programm ein und führen Sie es aus, um zu sehen, was passiert.

Ergebnis

In jedem Fall sollte i als 10 angezeigt werden. Es sollte keine Frage sein. Was ist nun mit der nächsten Frage?

Sagen Sie voraus, was Sie sehen werden, wenn Sie das obige Programm ausführen. Geben Sie dann das Programm ein und führen Sie es aus, um zu sehen, was passiert.

let i = 10;

console.log("before block: i =", i);

{
  i = 20;
  console.log("    in block: i =", i);
}

console.log(" after block: i =", i);

Ergebnis

Der Unterschied zur ersten Übung besteht darin, dass der Wert von i im Block geändert wurde. Es wären 10, 20, 20 in dieser Reihenfolge gewesen. Das bedeutet, dass das Programm mit oder ohne { und } auf die gleiche Weise funktionieren wird.

Auch hier gibt es keine Frage, nicht? Wenn Sie neugierig sind, entfernen Sie die { und } oben und führen Sie das Programm aus.

Block-Scope

Und nun die wichtigste Frage. Was passiert, wenn Sie wie folgt schreiben?

Sagen Sie voraus, was Sie sehen werden, wenn Sie das folgende Programm ausführen. Dann geben Sie es ein und führen es aus, um zu sehen, was passiert.

let i = 10;

console.log("before block: i =", i);

{
  let i = 1;
  console.log("    in block: i =", i);
}

console.log(" after block: i =", i);

Ergebnis

Der wichtigste Punkt ist die Verwendung von let in dem Block. In diesem Fall wird eine neue Variable erstellt. Das alte i, das in der ersten Zeile deklariert/definiert wurde, wird unsichtbar, aber es ist nicht weg. In einem Block deklarierte Variablen verschwinden beim Verlassen des Blocks. Wenn der Block endet, wird das ursprüngliche i wieder sichtbar, deshalb der ursprüngliche Wert von 10 wurde angezeigt.

Im Fall von for

Wie bei Iteration kurz beschrieben, wird eine for-Schleife normalerweise wie folgt geschrieben:

for (let i = 0; i < 3; i++) {
  console.log("  in for-loop: i =", i);
}

In diesem Fall ist i nur innerhalb der for-Schleife gültig. In diesem Fall beginnt der Block tatsächlich mit for. Überprüfen Sie dies mit dem folgenden Programm.

  1. Was erwarten Sie zu sehen, wenn Sie das folgende Programm ausführen, und warum? Geben Sie ihn dann ein und führen Sie ihn aus.

  2. Löschen Sie dann das let in for und führen Sie es aus. Erläutern Sie, worin der Unterschied zwischen dem obigen Ergebnis und dem, das Sie erhalten haben, besteht und warum.

let i = 10;
console.log("before for-loop: i =", i);

for (let i = 0; i < 3; i++) { // Löschen Sie let bei Frage 2.
  console.log("    in for-loop: i =", i);
}

console.log(" after for-loop: i =", i);

Ergebnis

Obwohl es Ausnahmen gibt, wird die Schleifenvariable fast immer nur innerhalb der for-Schleife benötigt, daher sollten Sie for immer in der Form von for (let i = 0; ...) verwenden, also let sollte immer in for eingefügt werden.

: Wiederholung von for

Dies ist ein wenig vom Thema abweichend, aber wenn Sie in der obigen Übung let entfernen, sollten Sie am Ende after for-loop: i = 3 sehen. Erklären Sie, warum der Wert von i am Ende 3 (statt 2) ist, indem Sie das Verhalten von for berücksichtigen.

Im Fall von Funktionen

Argumente von Funktionen werden automatisch als Variablen behandelt, die nur innerhalb dieser Funktion verwendet werden können.

Wenn Sie wie folgt schreiben, ist str eine Variable, die nur innerhalb dieser Funktion gültig ist:

function string_length(str) {	// str ist nur innerhalb dieser Funktion gültig
  ...
}

Es ist auch möglich, eine neue Variable innerhalb einer Funktion zu erstellen. Dies unterscheidet sich nicht von dem, was Sie bisher getan haben, da hier einfach eine Variable in dem Block erstellt wurde.

function string_length(str) {
  let length = 0;	// nur im Block gültig

  ...
}

Funktionen und Variablen

Es ist keine gute Idee, Variablen außerhalb der Funktion innerhalb der Funktion zu lesen oder zu schreiben (ändern).

Sie sollten nur im Aufruf (Argumente) und im Rückgabewert mit ihnen interagieren.

Schauen wir uns das folgende Programm an.

Sagen Sie voraus, was Sie sehen werden, wenn Sie das folgende Programm ausführen. Geben Sie sie dann ein und führen Sie sie aus, um zu sehen, was passiert.

// ! Das ist keine gute Art zu schreiben !
let sum = 10;

console.log(sum);
increment();
console.log(sum);

function increment() {
  sum += 1;
}

Ergebnis

Dieses Programm funktioniert gut, aber es kann auch Probleme verursachen.

Nehmen wir an, dass increment() sehr weit weg geschrieben ist (oder sogar in einer anderen Datei). Wenn man sich die erste Hälfte des Programms ansieht, sieht es nicht so aus, als ob der Wert von sum geändert worden wäre. Der Wert von sum wird nämlich unwissentlich geändert.

Angenommen, dass Sie sich in einer solchen Situation bemerkt haben, dass der Wert von sum falsch ist. Es ist sehr mühsam (vielleicht mehr, als Sie denken), herauszufinden, wo das Problem aufgetreten ist. Es könnte etwas leichter sein, wenn Sie wissen, dass increment() die einzige Funktion ist, die sum ändert, aber wenn verschiedene Funktionen sum ändern können, wird das Problem viel viel komplizierter.

Deshalb ist es viel besser, wenn Sie zum Beispiel wie folgt schreiben:

let sum = 10;

console.log(sum);
sum = increment(sum);
console.log(sum);

function increment(num) {
  return num + 1;
}

In diesem Fall ist es klar, dass in Zeile 4 eine Änderung an sum vorgenommen wurde.

Das heißt,

Sie sollten mit der Funktion nur via Argumenten und Rückgabewerten interagieren.

Mit anderen Worten, eine Funktion sollte so geschrieben sein, dass die Funktion

  • externe Informationen (Anweisungen von außen) nur über seine Argumente empfängt, und

  • nur im Rückgabewert Informationen an die Außenwelt (Außerhalb der Funktion) weitergibt, und

  • keine Auswirkungen auf die Außerhalb der Funktion hat.

Um es konkreter zu formulieren:

  • In einer Funktion sollten nur die als Argumente definierten Variablen und die in der Funktion definierten Variablen verwendet werden, und

  • Variablen außerhalb der Funktion sollten nicht direkt in der Funktion gelesen oder verändert werden.

Auch hier gilt: Ein gutes Programm ist eines, in dem möglichst wenige Fehler auftreten und die auftretenden Fehler leicht erkannt werden können. Das mag anfangs schwierig sein, aber bedenken Sie dies.

Anmerkung

Beachten Sie, dass Sie dieselbe Variable nicht mehrmals im selben Block deklarieren (definieren) können.

let a = 10;

console.log(a);

let a = 20;	// ! Falsch, man kann es nicht zweimal deklarieren !

console.log(a);