JavaScript/Variable

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Text-Info


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.

In JavaScript gibt es drei verschiedene Möglichkeiten Variablen zu deklarieren:

  • const: Symbolische Konstante; deklariert eine unveränderliche Variable
  • let: deklariert eine lokale Variable im Block Scope
  • var: deklariert eine Variable unabhängig von ihrem Scope (Gültigkeitsbereich).

var - Vater der Variablen[Bearbeiten]

Der Titel dieses Artikels ist mehrdeutig.


Bei JavaScripts Entstehung gab es nur das Schlüsselwort var, um eine Variable zu vereinbaren. Sie wird damit im aktuellen Scope (zum Beispiel innerhalb einer Funktion) angelegt.

  • JavaScript 1.0
  • Chrome
  • Firefox
  • IE
  • Opera
  • Safari
Beachten Sie: Ohne das Schlüsselwort var wird die Variable im globalen Scope erstellt. Dies birgt einige Probleme mit sich:
  • gleichlautende Variablen unterschiedlicher Scripte können sich gegenseitig überschreiben und so zu Fehlern bis hin zum Programmabsturz führen
  • ein Tippfehler beim Programmieren führt dazu, dass die ursprüngliche Variable leer bleibt und der Wert einer neu erstellten Variable zugewiesen wurde
Beispiel
root = '';  //Variable wird deklariert
Root = 15; // Falschschreibung führt zu neuer Variable
square = root * root; // erwartetes Ergebnis 225 :-(

Aus diesem Grund wurde der strict mode eingeführt, der eine Deklaration mit var erzwingt, sowie mit ES6 die Schlüsselwörter const und let.

Empfehlung: Verwenden Sie immer const und let und beachten Sie die Empfehlungen für die Praxis.

const und let[Bearbeiten]

Es ist guter Progrmmierstil am Anfang eines Scripts alle Parameter aufzulisten und benötigte Variablen anzulegen. Dabei wird heute zwischen Konstanten und Variablen unterschieden:

  • const legt eine Konstante an, die anfangs an einen Wert gebunden wird, welcher später nicht verändert werden kann (immutable) .
  • let legt eine Variable im aktuellen Gültigkeitsbereich an, die nicht gleich deklariert werden muss. Für diesen Fall erhält sie den Wert undefined.
  • Chrome
  • Firefox
  • IE 11
  • Opera
  • Safari

Details: caniuse.com

Variablendeklaration am Anfang eines Scripts.
const button = document.querySelector('#interaktiv'),
      output = document.querySelector('output'),
      PI     = 3.14; 
let   text   = 'Hallo Welt!';
let   alter;

Da sich die Referenzen auf DOM-Elemente für die Ein- und Ausgabe nicht ändern, werden sie mit const als Konstanten angelegt. Auch die Zahl PI ist unveränderlich. In der Mathematik und in vielen anderen Programmiersprachen wie PHP und Java (dort als static final) werden Konstanten in Großbuchstaben geschrieben.[1]

Die Variablen text und alter werden mit let angelegt, da sich der Wert innerhalb des Programmablaufs ändert. Bei text wurde der Anfangswert gleich angegeben wurde, bei Alter noch nicht .

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[Bearbeiten]

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.

Beispiel
// Berechnung Diagonale A4-Papier
let breite    = 210;
let höhe      = 297;
let diagonale = Math.sqrt(breite * breite + höhe * höhe);
let ausgabe   = 'Eine A4-Papierseite hat eine Diagonale von ' + Math.round(diagonale) + ' mm.';

console.log(ausgabe);

Die Werte für

  • breite, höhe und diagonale 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.

Beispiel
 breite = 5 + "px"

Gültigkeitsbereich[Bearbeiten]

Beachten Sie: Beim Arbeiten mit Variablen sucht der Interpreter die Variable zuerst im lokalen und anschließend im übergeordneten bis hin zum globalen Sichtbarkeitsbereich. Handelt es sich um eine Wertabfrage und findet er die Variable nicht, so löst er eine Ausnahme aus. Handelt es sich hingegen um eine Wertzuweisung und existiert die Variable nicht, dann erstellt der Interpreter die nicht existierende Variable automatisch als globale Variable.

Globale Variablen[Bearbeiten]

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.

Beispiel
let diagonale;
let 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);
}

In diesem Beispiel sind die Variablen diagonale und ausgabe global, da sie am Anfang des Script deklariert wurden..

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.

Beispiel
// 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);
Dieses Beispiel verdeutlicht, das globale Variablen auch gleichzeitig Eigenschaften vom window-Objekt sind.

Lokale Variablen[Bearbeiten]

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.

Beispiel
function berechneDiagonale(breite, höhe) {
  let diagonale = Math.sqrt(breite * breite + höhe * höhe);
  return Math.round(diagonale);
}

let 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.
Beispiel
function berechneWurzel(zahl)
{
  let ergebnis = Math.sqrt(zahl);
  return ergebnis;
}

function berechneDiagonale(breite, höhe)
{
  let diagonale = berechneWurzel(breite * breite + höhe * höhe);
  return Math.round(diagonale);
}
 
let ausgabe = 'Eine A4-Papierseite hat eine Diagonale von ' + berechneDiagonale(210, 297) + ' mm.';
In diesem Beispiel sind 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.
Beispiel
function berechneDiagonale(breite, höhe) {
  function berechneWurzel() {
    var ergebnis = Math.sqrt(breite * breite + höhe * höhe);
    return ergebnis;
  }
 
  let diagonale = berechneWurzel();
  return Math.round(diagonale);
}
 
let ausgabe = "Eine A4-Papierseite hat eine Diagonale von " + berechneDiagonale(210, 297) + " mm.";
In diesem Beispiel wurde die Funktion 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[Bearbeiten]

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).

Beispiel
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
Die Variable 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[Bearbeiten]

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.

Beispiel
// 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));
}

const diagonaleVonA4 = berechneDiagonaleVonA4Seite(); // starr
let diagonaleVonA5 = berechneDiagonale(210, 148);   // flexibel und wiederverwendbar
let 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.


Beispiel
const jahr = 2020;
let jahrtext = "Wir schreiben das Jahr ";
let ausgabe  = jahrtext + jahr;

alert(ausgabe); // "Wir schreiben das Jahr 2020"
In diesem Beispiel wird ein numerischer Wert an eine Zeichenkette angehängt.


Empfehlungen für die Praxis[Bearbeiten]

Empfehlung:
  • 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
      • const für unveränderliche Konstanten
      • let für Variablen
    • 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.
  • Variablennamen
    Benutzen Sie sprechende Namen, d. h. sinnvolle Bezeichnungen, die sich später zurückverfolgen lassen.
    ausgabe = breite * höhe; ist besser als a = 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.


Weblinks[Bearbeiten]

  1. SELF:Forum: const in CAPITALS? vom 06.01.2021