Tutorials › Teil 1: Grundlagen

Kapitel 3 von 16

Werte und Variablen

Ein Programm merkt sich Dinge. Es braucht dafür Schubladen mit Beschriftung, und die legt man so an:

const name = "Mathilda";
let punkte = 0;

punkte = punkte + 10;
punkte = punkte + 5;

zeige(name, "hat", punkte, "Punkte.");

Zwei Wörter, zwei Bedeutungen. const beschriftet eine Schublade und verschließt sie. let lässt sie offen.

const ist die Vorgabe

Der Reflex sollte const sein. Erst wenn du merkst, dass sich der Wert im Verlauf ändern muss, machst du ein let daraus.

Warum herum und nicht andersherum? Weil du beim Lesen von fremdem Code sofort weißt, woran du bist. Steht da const, brauchst du die restlichen vierzig Zeilen nicht danach abzusuchen, ob sich der Wert irgendwo unterwegs ändert. Er tut es nicht.

Ein Versuch, es doch zu tun, endet so:

const tage = 7;
tage = 8;
zeige("Diese Zeile wird nie erreicht.");

Eine Sache stiftet hier gern Verwirrung. const schützt die Beschriftung, nicht den Inhalt. Bei einem Array oder einem Objekt heißt das: Du kannst dem Ding keine neue Identität geben, aber du darfst hineingreifen.

const liste = [1, 2, 3];
liste.push(4);
zeige("Geht:", liste);

try {
  liste = [9, 9];
} catch (fehler) {
  zeige("Geht nicht:", fehler.message);
}

var kannst du vergessen

In jedem Skript in diesem Archiv steht var. Es war zwanzig Jahre lang die einzige Möglichkeit. Seit 2015 gibt es let, und seither gibt es keinen Grund mehr, var in neuem Code zu schreiben.

Der Unterschied, der wehtut, ist die Gültigkeit. let gilt in dem Block, in dem es steht, also zwischen den geschweiften Klammern. var schert sich nicht um Blöcke, es gilt in der ganzen umgebenden Funktion.

if (true) {
  var alt = "entkommt dem Block";
  let neu = "bleibt im Block";
  zeige("drinnen:", alt, "/", neu);
}

zeige("draußen:", alt);
zeige("und neu?", typeof neu);

Das führt zu Fehlern, die man stundenlang sucht. Besonders in Schleifen, dazu mehr in Kapitel 5.

Die Sorten von Werten

JavaScript kennt eine überschaubare Zahl grundlegender Typen. typeof verrät, womit du es zu tun hast.

zeige(typeof "Text");
zeige(typeof 42);
zeige(typeof 42.5);
zeige(typeof true);
zeige(typeof undefined);
zeige(typeof null);
zeige(typeof [1, 2, 3]);
zeige(typeof { a: 1 });
zeige(typeof function () {});

Zwei Zeilen davon sind gemein.

typeof null liefert "object". Das ist ein Fehler aus der allerersten Fassung von 1995, der nie behoben wurde, weil zu viel bestehender Code darauf aufbaut. Merk es dir als Kuriosität und prüf auf null lieber direkt mit === null.

typeof [1,2,3] liefert ebenfalls "object", weil ein Array technisch ein Objekt ist. Für die Frage, ob etwas eine Liste ist, gibt es Array.isArray().

Zahlen haben keinen eigenen Typ für ganze Zahlen. 42 und 42.5 sind beide number.

Zahlen rechnen nicht so, wie du denkst

zeige(0.1 + 0.2);
zeige(0.1 + 0.2 === 0.3);

Das ist kein Bug in JavaScript. Es passiert in praktisch jeder Programmiersprache, die Kommazahlen im Binärformat speichert, und ein Zehntel lässt sich im Binärsystem so wenig exakt darstellen wie ein Drittel im Dezimalsystem.

Praktische Konsequenz: Vergleich Kommazahlen nie auf Gleichheit. Und wenn es um Geld geht, rechne in Cent, also mit ganzen Zahlen, und teile erst bei der Ausgabe.

const preisInCent = 1999;
zeige((preisInCent / 100).toFixed(2), "Euro");

Text zusammensetzen

Der alte Weg mit dem Pluszeichen funktioniert, wird aber schnell unübersichtlich:

const gruss = "Hallo " + name + ", du hast " + punkte + " Punkte.";

Der bessere Weg benutzt Backticks und ${...}:

const name = "Mathilda";
const punkte = 15;

zeige(`Hallo ${name}, du hast ${punkte} Punkte.`);
zeige(`Mit dem Bonus wären es ${punkte * 2}.`);

Innerhalb der geschweiften Klammern darf jeder Ausdruck stehen, nicht nur ein Variablenname. Solche Zeichenketten dürfen außerdem über mehrere Zeilen gehen, ohne dass du \n schreiben musst.

Backticks sind auf der deutschen Tastatur die Taste links neben dem Rücktaste, zusammen mit Umschalt, und du musst danach einmal die Leertaste drücken.

Wahr, falsch und das Dazwischen

Manche Werte gelten als falsch, obwohl sie nicht false sind. Es sind genau sechs, und die Liste lohnt sich zu kennen:

false, 0, "" (leerer Text), null, undefined, NaN.

Alles andere gilt als wahr. Auch "0" als Text. Auch ein leeres Array. Auch ein leeres Objekt.

zeige("leerer Text:", Boolean(""));
zeige("Text mit Null:", Boolean("0"));
zeige("leeres Array:", Boolean([]));
zeige("Zahl Null:", Boolean(0));
const ausDemFormular = "5";

zeige("ohne Umwandlung:", ausDemFormular + 3);
zeige("mit Umwandlung: ", Number(ausDemFormular) + 3);
zeige("minus verhält sich anders:", ausDemFormular - 3);

Dass - die Umwandlung selbst vornimmt und + nicht, ist eine Inkonsequenz der Sprache. Verlass dich nicht darauf, wandle lieber ausdrücklich um.

undefined gegen null

Beide bedeuten „hier ist nichts", aber sie kommen aus verschiedenen Richtungen.

undefined kriegst du, wenn du nach etwas fragst, das es nicht gibt. Eine Variable ohne Zuweisung, eine Objekteigenschaft, die nie gesetzt wurde, ein fehlendes Funktionsargument. Niemand hat sich das ausgesucht, es ergibt sich.

null schreibst du selbst hin. Es heißt: Hier soll ausdrücklich nichts stehen. document.getElementById() liefert null, wenn es nichts findet, und teilt damit aktiv ein Ergebnis mit.

Die Unterscheidung wird in Kapitel 8 wichtig, wenn es um Objekte geht.

Wie man aus Werten Entscheidungen macht, steht im nächsten Kapitel.