Benutzer:Rolf b/JavaScript Variable
Editiert: JavaScript/Variable
Eine Variable lässt sich am besten mit einem Behälter, der genau einen Wert aufnehmen kann, vergleichen. Der Behälter ist ein logischer Speicherplatz mit einem (unveränderlichen) Namen und einem Wert, der verändert werden kann.
Für Werte gibt es eine ganze Reihe unterschiedlicher Typen, unter anderem Zahlen, logische Werte oder Zeichenketten. Eine Variable ist nicht auf einen bestimmten Wertetyp festgelegt, sie können in jeder Variable jeden Wertetyp speichern.
In JavaScript gibt es drei Anweisungen, die Variablen erzeugen:
- let: deklariert eine Variable im Block Scope
- const: deklariert eine symbolische Konstante. Sie verhält sich wie eine mit let deklarierte Variable, die schreibgeschützt ist.
- var: deklariert eine Variable global oder im Function Scope
Eine Erklärung zum Unterschied zwischen Block und Function Scope folgt im Abschnitt Gültigkeitsbereiche.
Wenn eine Variable deklariert ist, kann man einen Wert darin ablegen. Dieser Wert bleibt solange in der Variablen verfügbar, bis man ihn durch einen anderen Wert überschreibt, oder die Variable gelöscht wird.
Inhaltsverzeichnis
Deklaration
Bevor eine Variable verwendet werden kann, muss sie deklariert werden. Diese Deklaration verfolgt mehrere Zwecke.
- es soll helfen, Programmfehler durch einen Vertipper in Variablennamen zu vermeiden
- der Ort der Deklaration legt fest, welche Programmteile auf die Variable zugreifen können und wie lange die Variable existiert
- die verwendete Deklarationsanweisung legt weitere Regeln für den Zugriff fest
Da ein Behälter immer irgendetwas enthalten muss, und sei es auch nur Luft, sieht JavaScript für Variablen, die man deklariert hat, in denen aber noch nichts gespeichert wurde, den speziellen Wert undefined vor. undefined
ist ein JavaScript-Schlüsselwort, das für diesen speziellen Wert steht.
let
Die JavaScript Anweisung let deklariert eine oder mehrere Variablen innerhalb des Anweisungsblocks, in dem die let-Anweisung notiert wird. Steht die let-Anweisung außerhalb jeglicher Anweisungsblocks, ist die Variable nach Ausführung der let-Anweisung überall sichtbar und kann überall verwendet werden.
Um mehrere Variablen in einer let-Anweisung zu deklarieren, trennt man die Namen durch ein Komma.
let alter;
let name, vorname;
Fehler bei vorzeitiger Verwendung
console.log(alter); // Abbruch!
let alter;
const
Die JavaScript Anweisung const verhält sich genauso wie let, bis auf einen Unterschied: die so deklarierten Variablen können nicht mehr verändert werden. Man muss ihnen also sofort bei der Deklaration einen Wert geben. Wie das geht, folgt im Abschnitt Initialisierung.
var
Bei var handelt es sich um die ursprüngliche JavaScript-Anweisung zur Deklaration von Variablen, und sie verhält sich etwas anders als let
und const
. Eine var
Deklaration, die außerhalb einer Funktion notiert ist, gilt global. Steht sie innerhalb einer Funktion, gilt sie für die ganze Funktion, in der die var
Anweisung notiert ist. Es ist dabei ganz gleich, wo in der Funktion die var
-Anweisung steht, sie könnte auch ganz am Ende stehen. Diesen Vorgang nennt man Hebung (engl. hoisting). Das funktioniert, weil JavaScript Ihren Code erst ausführt, nachdem es das vollständige Script eingelesen und zur Ausführung vorbereitet hat.
function test() {
console.log(alter); // gibt undefined aus
console.log(falter); // Bricht das Script mit ReferenceError ab
var alter = 3;
}
test();
Das Script würde zunächst undefined
ausgeben, weil die Variable alter
innerhalb der test()
-Funktion zwar deklariert wurde, aber zum Zeitpunkt der Log-Ausgabe noch kein Wert zugewiesen wurde. Die Deklaration wird gehoben, die Wertzuweisung dagegen nicht. Der Versuch, falter
zu loggen, bricht das Script mit einem ReferenceError ab, weil eine Variable dieses Namens nicht vorhanden ist.
Zuweisung und Initialisierung
Um sinnvoll mit Variablen arbeiten zu können, muss man Werte in ihnen speichern. Das geschieht mit dem [[JavaScript/Operatoren/Zuweisungsoperator|Zuweisungsoperator] =
. Weil es häufig vorkommt, dass man einer deklarierten Variablen gleich einen Wert geben möchte, lassen sich Deklaration und Zuweisung auch kombinieren, man spricht dann von Initialisierung.
// Deklaration und Zuweisung getrennt
let breite;
breite = 300;
// Deklaration und Zuweisung zur Initialisierung zusammengefasst
let alter = 18;
// Initialisierung ist auch möglich, wenn mehrere Variablen auf einmal deklariert werden
let x = 100, y = 200;
Sie können außer Literalen auch einen Ausdruck notieren. In einem solchen Ausdruck können Sie beliebig Literale und andere Variablen verwenden. Die Betonung liegt hier auf andere - es ist nicht sinnvoll, beim Initialisieren der Variablen x die Variable x zu verwenden, weil sie in diesem Moment garantiert den Wert undefined
enthält.
Die Beispielvorlage hat keinen Inhalt! Bitte verwenden Sie dafür ausschließlich die vorgegebenen Beispiel-Module!
Die Initialisierung mit einem Ausdruck ist natürlich auch für let<code> und <code>var
verwendbar.
var
-Anweisung notiert ist.function test() {
var alter = 17;
console.log(alter); // gibt 17 aus
console.log(falter); // bricht das Script nicht mehr ab, aber gibt undefined aus
var falter = 92;
console.log(falter); // gibt 92 aus
}
Automatische Deklaration bei Zuweisung
Wie gezeigt, ist die Verwendung einer Variablen als Wert ist ohne Deklaration nicht möglich. Anders ist es bei der Zuweisung. Aus historischen Gründen erlaubt JavaScript eine Zuweisung an eine undeklarierte Variable und deklariert sie im Moment der Zuweisung automatisch, was unangenehme Folgen haben kann, weil diese Deklaration global erfolgt (dazu gleich mehr). Mit JavaScript 5 wurde der strikte Modus eingeführt, der dieses Verhalten abschaltet und der für neue Programme dringend empfohlen ist. Im strikten Modus führt jede Verwendung einer undeklarierten Variable zu einem Script-Abbruch.
Variablen und das globale Objekt
Ein Bestandteil der JavaScript-Laufzeitumgebung ist das Globale Objekt. In einer Browser-Umgebung finden Sie dieses Objekt in der Variablen window
. Variablen, die Sie auf globale Ebene mit var
deklarieren oder die automatisch deklariert wurden, finden Sie als Eigenschaften des window
-Objekts wieder.
Bei Variablen, die global mit let
oder const
deklariert wurden, erfolgt kein Eintrag im globalen Objekt.
Gültigkeitsbereiche
Wenn Sie neu in JavaScript einsteigen und noch nicht wissen, was Anweisungsblöcke oder Funktionen sind, sollten Sie diesen Abschnitt zurückstellen.
Wie eingangs erwähnt, wird durch den Ort der Variablendeklaration festgelegt, welche Programmteile die Variable sehen können und wie lange sie existiert. Diese Sichtbarkeit wird durch so genannte Gültigkeitsbereiche (engl. Scopes) geregelt.
Jedem Anweisungsblock, also Codezeilen, die in geschweifte Klammern eingeschlossen sind, ordnet JavaScript einen solchen Gültigkeitsbereich zu. Diese Zuordnung findet zur Laufzeit statt, nicht nur einmal beim Einlesen des Scripts. Wenn Sie also eine Funktion schreiben, wird bei jedem Aufruf dieser Funktion ihr Gültigkeitsbereich neu erzeugt. Wenn die Funktion endet, endet auch die Lebensdauer dieses Gültigkeitsbereichs, und alle Variablen, die sich darin befinden, werden gelöscht. (Diese Aussage ist nur bedingt korrekt, es würde aber zu weit führen, an dieser Stelle auf Closures und ihre Auswirkungen einzugehen).
Außerdem gibt es noch den globalen Gültigkeitsbereich, der dann verwendet wird, wenn kein Anweisungsblock begonnen wurde.
Bei Gültigkeitsbereichen gibt es zwei Aspekte zu beachten. Zum einen ihre Sichtbarkeit, zum anderen ihre Lebensdauer.
Stellen Sie sich Gültigkeitsbereiche wie einen Stapel Blätter vor - weiße und gelbe. Auf jedem Blatt können Variablennamen und Werte dafür notiert werden. Zu Beginn haben wir nur ein gelbes Blatt - der globale Gültigkeitsbereich.
An jeder Stelle, wo Ihr Programmcode einen Anweisungsblock bildet, wird ein Immer dann, wenn der Programmablauf den Beginn eines Anweisungsblocks passiert, wird eine neues, weißes Blatt auf den Stapel gelegt. Wird eine Funktion aufgerufen, legen wir ein gelbes Papier auf den Stapel.
Wird eine Variable mit let oder const deklariert, wird das auf dem Blatt vermerkt, dass gerade zuoberst liegt. Anders ist es bei einer Deklaration mit var. Dafür wird das oberste gelbe Blatt - ein Funktions-Scope - gesucht, um die Variable darauf zu vermerken. Mit einer Ausnahme: eine var-Deklaration darf eine let- oder const-Deklaration nicht überschreiben. Das ist ein Syntaxfehler, der dazu führt, dass das Script gar nicht erst startet.
Beim Abrufen eines Wertes, der in einer Variablen steht, wird der Stapel von oben nach unten nach dem gewünschten Namen durchsucht. Das klingt aufwänd
Variablendeklarationen mit let oder const erfolgen als neue Zeilen der Tabelle, aber auf dieser neuen Folie. Es sei denn, man deklariert eine Variable, deren Name schon in der Tabelle steht. In diesem Fall wird in der Zeile mit dem vorhandenen Namen ein Stück Papier auf die Folie geklebt, das den Wert aus der unteren Folie verdeckt. Die existierende Variable wird durch die neue Deklaration überlagert.
Und dann gibt es noch den Fall, dass einer Variablen etwas zugewiesen werden soll, die auf einer tiefer liegenden Folie deklariert ist. Nun kommt der Cutter zum Einsatz. In alle Folien, die über der deklarierenden Folie liegen, wird ein Loch geschnitten, so dass auf
Wird der Anweisungsblock verlassen, wird seine Folie entfernt und weggeworfen. Eventuell aufgeklebte Papierchen verschwinden dabei mit, so dass die alten Werte von überlagerten Variablen jetzt wieder sichtbar werden.
Wird ein Anweisungsblock dadurch betreten, dass eine Funktion aufgerufen wird, bekommt die dafür verwendete Folie ein Lesezeichen. Wird nun während der Funktionsausführung eine Variable mit var
deklariert, werden Folien ohne Lesezeichen kurz hochgeblättert, bis das Funktionslesezeichen gefunden ist, und die Variable dort eingetragen.
Gültigkeitsbereiche
let a4breite = 210, a4höhe = 297;
let diagonale = berechneDiagonale(a4breite, a4höhe);
console.log('Die Diagonale hat eine Länge von ' + diagonale + ' mm.');
function berechneDiagonale(breite, höhe)
{
quadratsumme = breite * breite + höhe * höhe;
var diagonale = Math.sqrt(quadratsumme);
return diagonale;
}
In diesem Beispiel kommen zwei Gültigkeitsbereiche vor. Zum einen der globale Bereich. In diesem werden die Variablen breite
, höhe
und diagonale
deklariert. Für der Initialisierung der Variablen diagonale
wird die Funktion berechneDiagonale
aufgerufen.
Dieser Aufruf legt eine zweite Folie auf, und es finden drei Deklarationen statt:
a4breite
- dieser Name ist neu, es wird eine neue Zeile erstellt
a4höhe
- ebenfalls neu, es wird eine weitere neue Zeile erstellt
diagonale
-.
diagonale
- auch dieser Name existiert schon, es wird ein weiteres Papierchen aufgeklebt
breite
|
dieser Name ist neu, es wird eine neue Zeile erstellt |
höhe
|
ebenfalls neu, es wird eine weitere neue Zeile erstellt |
diagonale
|
dieser Name existiert bereits auf der unteren Folie. Die Funktionsfolie bekommt also ein Papierchen aufgeklebt |
Die Parameter breite
und höhe
werden nun noch mit den als Argument übergebenen Werten befüllt, und dann beginnt die Ausführung der Funktion. Das erste, was sie antrifft, ist eine Zuweisung an eine undeklarierte Variable. Da der strikte Modus nicht eingeschaltet wurde, bedeutet das: Alle Folien beiseite legen und auf der globalen Folie einen neuen Eintrag für quadratSumme
erstellen. Darin wird die Summe der Seitenquadrate gespeichert. In der zweiten Zeile findet eine Zuweisung statt. Zunächst wird der zuzuweisende Wert bestimmt, und dafür wird quadratSumme
benötigt. Diese Variable steht auf der untersten Folie und ist nicht überklebt, ihr Wert wird
Das bedeutet, dass man es schon beim Öffnen des ersten Anweisungsblocks mit zwei Gültigkeitsbereichen zu tun hat. Dass ein neuer Gültigkeitsbereich eröffnet wurde, Der Zugriff auf diese Gültigkeitsbereiche erfolgt von i
befindet sich eine Variable in einem Gültigkeitsbereich (engl: Scope). Die bisherigen Beispiele haben Variablen im sogenannten globalen Gültigkeitsbereich erzeugt, das heißt: sie werden deklariert und bleiben vorhanden, bis die HTML Seite, auf der das Script steht, wieder verlassen wird. Eine solche Gültigkeit kann gelegentlich erforderlich sein, in den meisten Fällen ist das aber nicht nötig. Eine globale Gültigkeit bedeutet nämlich auch ein hohes Konfliktpotenzial, sobald man JavaScript-Programme mit mehr als nur einigen Zeilen schreibt. Wären alle Variablen global, müsste man sehr genau Buch führen, welche man wofür verwendet.
{{Beispiel|Programmierung mit globalen Variablen
let breite = 210, höhe = 297;
let diagonale = berechneDiagonale(breite, höhe);
console.log('Die Diagonale hat eine Länge von ' + diagonale + ' mm.');
function berechneDiagonale(breite, höhe)
{
quadratsumme = breite * breite + höhe * höhe;
diagonale = Math.sqrt(quadratsumme);
return diagonale;
}
Die Funktion benötigt zwei Zwischenergebnisse: quadratsumme und diagonale. Diese deklariert sie nicht, wodurch sie automatisch im globalen Gültigkeitsbereich gesucht und bei Bedarf angelegt werden. Was die Funktion nicht weiß: Es gibt schon eine Variable diagonale
, die sie einfach mal überschreibt. Auf diese Weise entstehen schwer findbare Programmfehler.
Lokaler Gültigkeitsbereich mit var
Um Abhilfe zu schaffen, erzeugt jede Funktion in JavaScript ihren eigenen Gültigkeitsbereich. Er wird erzeugt, wenn die Funktion aufgerufen wird, und alle Variablen, die innerhalb der Funktion deklariert werden, existieren darin. Außerhalb der Funktion sind diese Variablen nicht sichtbar.
Arbeitsdaten in lokalen Variablen
var breite = 210, höhe = 297;
var diagonale = berechneDiagonale(breite, höhe);
console.log('Die Diagonale eines A4-Blattes beträgt ' + diagonale + ' mm.');
function berechneDiagonale(breite, höhe)
{
var quadratsumme = breite * breite + höhe * höhe;
var wurzel = Math.sqrt(quadratsumme);
return Math.round(wurzel);
}
Die abgeänderte Funktion deklariert die Variablen, die sie für ihre Arbeit braucht, mit var
. Die so erzeugten Variablen quadratsumme und diagonale werden dadurch im Gültigkeitsbereich der Funktion erzeugt und verschwinden wieder, sobald die Funktion zum Aufrufer zurückkehrt.
So, wie man auch Funktionen ineinander schachteln kann, sind auch die ihnen zugehörigen Gültigkeitsbereiche ineinander verschachtelt. Damit ist gemeint, dass eine Funktion nicht nur die Variablen nutzen kann, die sie selbst deklariert, sondern auch alle Variablen des Gültigkeitsbereichs, in dem sie definiert wurde.
Lokaler Gültigkeitsbereich mit let oder const
Deklarationen mit let
und const
gehen noch einen Schritt weiter. Um Variablen sozusagen punktgenau deklarieren zu können, reicht ein Scope auf Funktionsebene nicht aus. Deswegen gelten let
und const
nur exakt innerhalb des Anweisungsblocks, in dem sie notiert sind.
Block Scope mit let
let quadratSumme = 0;
for (let i=0; i<10; i++) {
const iQuadrat = i * i;
quadratSumme = quadratSumme + iQuadrat
}
console.log('Summe der Quadrate von 1 bis 10 ist ' + quadratSumme);
In diesem Beispiel werden der Zähler i und sein Quadrat nur innerhalb der for
-Anweisung benötigt. Darum wird iQuadrat innerhalb des Anweisungsblocks für for
mit let deklariert. Bei i
liegt ein Sonderfall vor. Die Klammern der for
-Anweisung bilden für let und const einen eigenen Block, und der eigentliche Anweisungsblock der for
-Anweisung ist darin eingeschachtelt.
Dadurch wird im Beispiel mit 3 Gültigkeitsbereichen gearbeitet. iQuadrat
befindet sich im Block-Scope des Anweisungsblocks der for
-Schleife. i
liegt bereits in dessen Eltern-Scope, der von der for
-Anweisung implizit gebildet wurde. Und quadratSumme
ist im globalen Gültigkeitsbereich deklariert (oder im Funktions-Scope, falls das Beispiel in einer Funktion stehen würde).
Überdecken von Variablen
Neue Möglichkeiten schaffen auch neue Probleme. Betrachten Sie dieses Beispiel:
Block Scope mit let
let summe = 0;
for (let i=0; i<10; i++) {
let summe = summe + i;
}
console.log('Die Summe ist ' + summe);
Die Ausgabe ist: "Die Summe ist 0". Der Grund dafür ist, dass im Anweisungsblock irrtümlich die let
-Anweisung verwendet wird, was eine neue Variable erzeugt. Es ist absolut legitim, in einem Gültigkeitsbereich Variablen zu deklarieren, die genauso heißen wie Variablen, die in einem weiter außen liegenden Gültigkeitsbereich deklariert wurden. Die weiter innen deklarierten Variablen verdecken dann die äußeren und machen sie unzugänglich.
Dieses Verhalten ist gewollt und auch wünschenswert. Man möchte ja gerade erreichen, dass man bei der Verwendung von lokalen Variablen unabhängig von den übergeordneten Gültigkeitsbereichen ist. Variablenzugriff aus dem aktuellen Gültigkeitsbereich hinaus - vor allem aus dem Funktions-Gültigkeitsbereich - sollten stets gut geplant sein und nur mit gutem Grund stattfinden.
Zugriff auf überdeckte Variablen
Grundsätzlich gilt: überdeckte Variablen sind überdeckt und nicht erreichbar.
Es gibt aber Variablen oder Schnittstellen, die vom Browser im globalen Gültigkeitsbereich bereitgestellt werden und relativ gewöhnliche Namen tragen, wie location
oder document
. Wenn man diese Schnittstellen nicht braucht, ist man leicht versucht, solche Namen auch für lokale Variablen zu verwenden. Schlimmer noch, es könnte passieren, dass eine neue Schnittstelle eingeführt wird, unter einem Namen, den man bisher für frei hielt.
Um dennoch auf solche globalen Objekte zugreifen zu können, stellt JavaScript ein spezielles Objekt bereit, das die globalen Variablen als Objekteigenschaft zur Verfügung stellt. Dieses Objekt findet sich im Browser in der globalen Variablen window
. Es ist zwar möglich, aber überhaupt keine gute Idee, eine lokale Variable dieses Namens zu erzeugen.
Wenn Sie im Browser einen Worker (Web oder Service Worker) erzeugen, bekommt er einen eigenen, unabhängigen globalen Gültigkeitsbereich. Diesen erreichen Sie über die globale Variable self
. Falls Sie Code haben, der sowohl im normalen Browser-Umfeld wie auch in einem Worker laufen soll, wäre es unpraktisch, zwischen window
und self
unterscheiden zu müssen. Deshalb wird self
auch als Alias von window
bereitgestellt.
In node.js, einer anderen JavaScript-Ablaufumgebung, heißt diese spezielle Variable global
.
var
deklarieren, finden Sie auch als Eigenschaften des globalen Objekts wieder. Aber eine mit let
oder const
deklarierte Variable ist über das globale Objekt nicht erreichbar, auch nicht, wenn die Deklaration im globalen Gültigkeitsbereich stattfand.Und was tut man, wenn man unbedingt auf das globale Objekt zugreifen muss, aber window
oder self
nicht erreichbar sind? Vor Einführung des strikten Modus gab es dafür einen Trick. Man rief eine Funktion auf und verwendete darin die spezielle Variable this
. Im strikten Modus funktioniert das nicht, dort enthält this
entweder null
oder ein Objekt, für das die Funktion als Methode aufgerufen wurde. Die Antwort heißt: Wenn Sie sich den Weg verbaut haben, ist er verbaut. Gestalten Sie Ihren Code um. Verwenden Sie keine globale Variable namens window
oder self
.
var
Durch das Schlüsselwort var
wird eine Variable vereinbart. Sie wird damit im aktuellen Scope (zum Beispiel innerhalb einer Funktion) angelegt. Ohne das Schlüsselwort var
wird die Variable im globalen Scope erstellt.
Sie kann entweder ohne Wert instantiiert werden:
var alter;
Oder der Anfangswert kann gleich angegeben werden:
var alter = 18;
Anstelle der 18 kann ein beliebiger Ausdruck stehen. Das Schema lautet also:
var Bezeichner = Ausdruck;
Wird ihr anfänglich kein Wert zugewiesen, so ist sie vom Typ undefined
. Nachdem eine Variable erstellt wurde, kann mit dem Variablennamen gearbeitet werden. Das Speichern von Werten erfolgt über den Zuweisungsoperator.
Datentypen
Da JavaScript keine starke Typisierung aufweist, können in einer Variable alle Arten von Werten gespeichert werden. Der Typ einer Variable richtet sich daher implizit nach dem Typ des darin gespeicherten Wertes. Gegebenenfalls notwendige Typänderungen werden eigenständig im Hintergrund vorgenommen.
// Berechnung Diagonale A4-Papier
var breite = 210;
var höhe = 297;
var diagonale = Math.sqrt(breite * breite + höhe * höhe);
var ausgabe = 'Eine A4-Papierseite hat eine Diagonale von ' + Math.round(diagonale) + ' mm.';
console.log(ausgabe);
Die Werte für
-
breite
,höhe
unddiagonale
sind vom Datentyp number -
ausgabe
enthält einen String; also wird der gesamte Wert zu einer Zeichenkette
So ist zum Beispiel die folgende Anweisung in Javascript möglich, ihr Variablentyp ist string
; in vielen anderen Programmiersprachen hätte dies eine Fehlermeldung zur Folge.
breite = 5 + "px"
Gültigkeitsbereich
Globale Variablen
Globale Variablen sind im gesamten Dokument gültig und stehen jederzeit zur Verfügung. Wenn innerhalb von Funktionen Variablen ohne ein lokal machendes Schlüsselwort (var
, let
oder const
) deklariert werden, dann sind diese Variablen global. Wird eine var Deklaration außerhalb einer Funktion ausgeführt, erzeugt das ebenfalls eine globale Variable.
var diagonale;
var ausgabe;
berechneDiagonale(210, 297);
ausgabe = 'Eine A4-Papierseite hat eine Diagonale von ' + diagonale + ' mm.';
function berechneDiagonale(breite, höhe)
{
diagonale = Math.sqrt(breite * breite + höhe * höhe);
diagonale = Math.round(diagonale);
}
Technisch gesehen handelt es sich bei globalen Variablen um Eigenschaften eines Objektes, das die Javascript-Laufzeitumgebung bereitstellt. Dieses Objekt dient als Ausgangspunkt für alle Daten eines Javascript-Programms und wird auch oberstes oder Wurzelobjekt genannt. Wird eine globale Variable erzeugt, wird das Wurzelobjekt automatisch um eine Eigenschaft mit diesem Namen erweitert. Lesen von globalen Variablen ist gleichbedeutend mit einem Zugriff auf die gleichnamige Eigenschaft des Wurzelobjekts.
Man kann das Wurzelobjekt nutzen, um sicherzustellen, auf eine globale Variable diesen Namens zuzugreifen. Bei Javascript im Browser ist dieses Objekt in der globalen Variablen window
zu finden. In anderen Umgebungen, wie Node.js, kann es z. B. global
heißen. Darüber hinaus definieren noch viele Browser die globale Variable self
und legen dort eine Referenz auf das globale Objekt ab.
Abzuraten ist von der früher gezeigten Idee, eine Funktion aufzurufen und darin die Kontextvariable this
zu verwenden. Neuerer JavaScript-Code sollte immer im strengen Modus (strict mode) geschrieben werden, und darin funktioniert diese Methode nicht mehr.
// Globale Variable
var ausgabe = "Hallo Welt";
// Globale Funktion
function add5(a){return a+5;};
// Abfrage vordefinierter globaler Funktionen.
alert(alert);
alert(window.alert);
alert(self.alert);
// Abfrage globaler Funktionen
alert(add5);
alert(window.add5);
alert(self.add5);
// Abfrage globaler Variablen
alert(ausgabe);
alert(window.ausgabe);
alert(self.ausgabe);
// Auch möglich aber unsinnig
alert(window.self.ausgabe);
window
-Objekt sind.Lokale Variablen
Lokale Variablen werden innerhalb von Funktionen deklariert. Sie sind nur innerhalb dieser Funktion gültig. Wenn eine Funktion mit Parametern definiert wird, so sind diese Parameter implizit als lokale Variablen definiert und erhalten bei Aufruf automatisch die übergebenen Argumente zugewiesen.
function berechneDiagonale(breite, höhe) {
var diagonale = Math.sqrt(breite * breite + höhe * höhe);
return Math.round(diagonale);
}
var ausgabe = 'Eine A4-Papierseite hat eine Diagonale von " + berechneDiagonale(210, 297) + " mm.';
breite
, höhe
und diagonale
sind lokale Variablen in der Funktion berechneDiagonale
. Außerhalb der Funktion existiert in diesem Beispiel nur eine globale Variable namens ausgabe
.function berechneWurzel(zahl)
{
var ergebnis = Math.sqrt(zahl);
return ergebnis;
}
function berechneDiagonale(breite, höhe)
{
var diagonale = berechneWurzel(breite * breite + höhe * höhe);
return Math.round(diagonale);
}
var ausgabe = 'Eine A4-Papierseite hat eine Diagonale von ' + berechneDiagonale(210, 297) + ' mm.';
zahl
und ergebnis
lokale Variablen der Funktion berechneWurzel
. Sie sind nur innerhalb dieser Funktion sichtbar. Die Variablen breite
, höhe
und diagonale
sind lokale Variablen in der Funktion berechneDiagonale
. Im globalen Sichtbarkeitsbereich findet sich nur die Variable ausgabe
.function berechneDiagonale(breite, höhe) {
function berechneWurzel() {
var ergebnis = Math.sqrt(breite * breite + höhe * höhe);
return ergebnis;
}
var diagonale = berechneWurzel();
return Math.round(diagonale);
}
var ausgabe = "Eine A4-Papierseite hat eine Diagonale von " + berechneDiagonale(210, 297) + " mm.";
berechneWurzel
innerhalb des Funktionskörpers von berechneDiagonale
definiert. Daher sieht die Funktion berechneWurzel
auch die lokalen Variablen breite
und höhe
der Funktion berechneDiagonale
und kann somit darauf zugreifen. Die Variable ergebnis
bleibt hingegen eine lokale Variable von berechneWurzel
und ist auch nur dort sichtbar.Bei Verwendung geschachtelter Funktionen zeigt es sich, dass Javascript in mehr als nur einem lokalen Kontext nach Variablen sucht. Die Funktion berechneWurzel
ist zum einen Träger eines eigenen lokalen Kontextes, ist aber selbst auch Teil des Kontextes von berechneDiagonale
und kann darum die lokalen Variablen dieses Kontextes ebenfalls verwenden.
Scope und Hebung
var
ist das klassische Javascript Syntaxelement zum Definieren lokaler Variablen. Die Semantik von var
-Variablen unterscheidet sich von der gewohnten Semantik in Sprachen wie C oder Java dahingehend, dass solche Variablen keinen Block-Scope kennen. Was mit var
vereinbart wird, wird vom JavaScript-Interpreter so behandelt, als hätte diese Vereinbarung am Beginn des Script-Blocks bzw. der Funktion stattgefunden, worin die var-Deklaration steht. Diese Verschiebung des Deklarationspunktes nennt man Hebung (hoisting).
testVar = "abc";
function test() {
testVar = 17;
alert(testVar); // gibt "17" aus
if (5 > 1) {
var testVar = 3;
}
}
test();
alert(testVar); // gibt "abc" aus, testVar wurde nicht überschrieben
testVar
ist lokal zur Funktion test()
, weil das Hoisting dafür sorgt, dass die Deklaration aus dem if heraus an den Anfang gezogen wird.Anders verhält sich let. Dieses Schlüsselwort ist mit ECMAScript2016 eingeführt worden, um die in anderen Sprachen bekannte Scope-Semantik auch in ECMAScript nutzen zu können. Mit let definierte Variablen unterliegen nicht der Hebung, und gelten nur in dem Anweisungsblock, in dem sie definiert wurden.
Arbeiten mit Variablen
Der große Vorteil einer Variable ist, dass man ihr etwas zuweisen und damit arbeiten kann. Anstatt also feste Werte im Programm zu verwenden, bezieht man sich auf den Wert, der in einer Variable gespeichert wurde. Hierdurch werden Programme erst flexibel und Funktionen können verallgemeinert werden.
// Fix und nicht flexibel
function berechneDiagonaleVonA4Seite()
{
return Math.round(Math.sqrt(210 * 210 + 297 * 297));
}
// Flexibel durch Verwendung von Variablen
function berechneDiagonale(breite, höhe)
{
return Math.round(Math.sqrt(breite * breite + höhe * höhe));
}
var diagonaleVonA4 = berechneDiagonaleVonA4Seite(); // starr
var diagonaleVonA5 = berechneDiagonale(210, 148); // flexibel und wiederverwendbar
var diagonaleVonA3 = berechneDiagonale(420, 297); // flexibel und wiederverwendbar
Ein weiterer Vorteil und Nachteil zugleich ist, dass es einer Variable erstmal egal ist, was sie für einen Wert beinhaltet. Dies kann eine Zahl, eine Zeichenkette, ein Array, eine Funktion oder sonstiges Objekt sein. Wenn man hingegen einen bestimmten Typ erwartet, der verarbeitet werden soll, dann muss man unter Umständen zuerst prüfen, ob das Objekt in der Variable kompatibel ist oder konvertiert werden kann.
JavaScript führt eine implizite Typkonvertierung durch, wenn man selber nicht darauf achtet. Kann der Typ für eine bestimmte Operation nicht konvertiert werden, dann wird eine Ausnahme ausgelöst oder es wird ein Standardwert zurückgegeben. Es werden aber auch Funktionen bereitgestellt, um eine explizite Typkonvertierung durchzuführen. Diese geben mehr Kontrolle, wie man auf eine unzureichende Konvertierung reagieren möchte.
var jahrtext = "Wir schreiben das Jahr ";
var jahrzahl = 2012;
var ausgabe = jahrtext + jahrzahl;
alert(ausgabe); // "Wir schreiben das Jahr 2012"
Empfehlungen für die Praxis
- Verwenden Sie den strict mode, um durch Tippfehler versehentlich erzeugte globale Variablen auszuschließen.
- Scope (Gültigkeit):
Benutzen Sie Variablen – soweit möglich – lokal und deklarieren Sie auch dort. So wird ihr Script übersichtlicher und leichter zu debuggen.- Deklarieren Sie globale Variablen am Anfang des Scripts mit
var
. - Halten Sie den globalen Namensraum sauber. Jedes Programm benötigt einen gewissen Stamm an globalen Daten, es ist aber hilfreich, diese nicht in mehreren Variablen zu verteilen. Nutzen Sie statt dessen eine einzige globale Variable und speichern Sie dort ein Namensraum-Objekt. In dessen Eigenschaften können Sie globale Informationen für Ihr Projekt ablegen.
- lokale Variablen können Sie mit let deklarieren.
- Deklarieren Sie globale Variablen am Anfang des Scripts mit
- Variablennamen
Benutzen Sie sprechende Namen, d.h. sinnvolle Bezeichnungen, die sich später zurückverfolgen lassen.ausgabe = breite * höhe;
ist besser alsa = b * h;
- Beachten Sie die Regeln für selbstvergebene Namen, z.B:
- Variablen sind case-sensitive, also achten Sie immer auf Groß-und Kleinschreibung.
- CamelCase
Besser lesbar ist das so genannte CamelCase, in dem die ersten Buchstaben der einzelnen Bestandteile des Namens groß geschrieben werden.
diagonale
undausgabe
global.