Orlok: const let var

Beitrag lesen

Fortsetzung folgt!

Die angesprochene Besonderheit in Zusammenhang mit dem Operator typeof zeigt sich wenn versucht wird, den Typ des Wertes einer erst zu einem späteren Zeitpunkt mittels const oder let deklarierten Variable zu bestimmen, wenn sich die Variable also in der Temporal Dead Zone befindet. Erinnern wir uns aber zunächst daran, was passiert wenn wir das Gleiche bei einer mit var deklarierten Variable versuchen.

console.info(typeof Worf); // undefined

var Worf = 'Klingon';

Da mittels var deklarierte Variablen gehoistet werden, sie also erzeugt und mit dem Wert undefined initialisiert werden, bevor die Ausführung des mit dem jeweiligen Kontext assoziierten Codes beginnt, wird hier vom Operator typeof natürlich undefined zurückgegeben. Soweit keine Überraschung. ;-)

Nun sehen wir uns an was passiert, wenn wir mit dem Operator typeof versuchen den Wert einer Variable zu bestimmen, die überhaupt nicht deklariert wurde:

console.info(typeof Riker); // undefined

Auch hier wird vom Operator typeof standardgemäß der String 'undefined' zurückgegeben.

Es wäre also zu erwarten, dass die Prüfung des Wertes einer noch nicht im Code deklarierten const- oder let-Variable ebenfalls den Typbezeichner undefined zurückgibt …

function Enterprise ( ) {
  // TDZ start
  console.info(typeof Data); // Reference Error
  // TDZ end
  let Data = 'Android';
}

Enterprise( );

… aber wie das Beispiel oben zeigt, fliegt uns statt dessen unser Programm mit einem Reference Error um die Ohren! – Also, was ist hier los? ;-)

Um zu verstehen was hier passiert, müssen wir uns zunächst einmal die Semantik des Operators typeof näher ansehen, beziehungsweise genauer gesagt, was passiert wenn es sich bei dem Operanden, also dem Ausdruck auf der rechten Seite, um eine Referenz handelt.

// global environment

(function outer ( ) {
  // function environment

  (function inner ( ) {
    // function environment
    console.info(typeof LaForge); // undefined
  }( ));

}( ));

Handelt es sich wie in dem Beispiel hier bei dem Operanden von typeof um eine Referenz, dann wird natürlich versucht diese aufzulösen. Das heißt, es wird als erstes in der nächsten lexikalischen Umgebung nachgesehen, ob diese über eine Bindung für den gesuchten Bezeichner verfügt. Das wäre hier also die lexikalische Umgebung, die mit dem Ausführungskontext der Funktion mit dem Bezeichner inner assoziiert ist.

Da diese lexikalische Umgebung zwar über keine Bindung für den gesuchten Bezeichner verfügt, aber dafür über eine Referenz auf die lexikalische Umgebung des äußeren Kontextes, wird entsprechend dort weitergesucht. Ebenfalls erfolglos. Da schließlich auch in der globalen Umgebung keine Variable oder Funktion mit dem Bezeichner LaForge deklariert wurde, handelt es sich hier also um eine nicht auflösbare Referenz (Unresolvable Reference). Und für diesen Fall ist standardmäßig vorgesehen, dass von typeof der Wert 'undefined' zurückgegeben wird.

Jetzt haben wir aber schon im letzten Teil der Antwort festgestellt, dass Variablen, die mittels const oder let deklariert wurden, zwar nicht wie var-Variablen gehoistet werden, in dem Sinne, dass sie mit einem (Default-)Wert initialisiert werden, aber dass sie eben dennoch vor dem Eintritt in den jeweiligen Scope an die dazugehörige lexikalische Umgebung gebunden werden.

Das heißt, bezogen auf das Ursprungsbeispiel mit Data handelt es sich bei dem Operanden von typeof nicht um eine unauflösbare Referenz, denn eine Bindung für diesen Bezeichner in der lexikalischen Umgebung der Funktion Enterprise besteht ja. Es ist eben nur nicht möglich auf die Variable zuzugreifen, da diese nicht Initialisiert wurde. – Deswegen: Reference Error.

Redeclaration

Ein weiterer Unterschied zwischen solchen Variablen die mittels var deklariert werden und solchen die mittels const oder let deklariert werden besteht im Hinblick auf das Verhalten, das sich zeigt wenn im gleichen Gültigkeitsbereich für den selben Bezeichner mehr als eine Deklaration vorgenommen wird.

var number = 64;
console.log(number); // 64

var number = 128;
console.log(number); // 128

Bei var-Variablen passiert hier nichts, außer dass bei einer weiteren Deklaration, so denn dabei wie in dem Beispiel ein Wert zugewiesen wird, der alte Wert überschrieben wird. Es wird also bei der Evaluierung des jeweiligen Ausführungskontextes in diesem Fall kein Fehler erzeugt, sondern eben schlicht eine Variablenbindung hinterlegt, es wird also so getan, als wäre die zweite Deklaration nur eine Referenz oder ein Zuweisungsausdruck.

// Type Error before execution
let word = 'foo';

let word = 'foo';

Das sieht bei let und freilich auch bei const anders aus. Hier wird sowohl im schlampigen also auch im strikten Ausführungsmodus grundsätzlich eine Ausnahme geworfen.

// Type Error before execution
function foo (bar) {
  let bar = 12;
}

Dabei spielt es auch keine Rolle, ob wie in dem Beispiel oben der gleiche Bezeichner verwendet wird wie bei einem formalen Parameter, oder ob im gleichen Gültigkeitsbereich eine Variable mit einem anderen Typ existiert, oder ob dort eine Funktion mit dem entsprechenden Bezeichner deklariert wurde. Eine Redeklaration von const- und let-Variablen produziert immer einen Fehler.

Da die mehrfache Verwendung eines Bezeichners für verschiedene Variablen oder Funktionen innerhalb des selben Gültigkeitsbereichs wohl praktisch immer auf eine Nachlässigkeit des Programmierers zurückzuführen ist, ist dieses Verhalten auch durchaus begrüßenswert.

Passiert so etwas mit einer var-Variablen, dann wird wie gesehen keine Ausnahme geworfen, und die Fehlersuche kann sich unter Umständen als schwierig erweisen, sofern man keine Entwicklungsumgebung verwendet die smart genug ist die Mehrfachdeklaration anzuzeigen.


Zusammenfassend lässt sich also sagen, dass const und let im Vergleich zu var die Befolgung weit strikterer Regeln einfordern, selbst wenn das Programm nicht im im Strict Mode ausgeführt wird, das heißt, durch ihre Verwendung kann eine ganze Reihe potentiell fehlerträchtiger Praktiken von vorneherein ausgeschlossen werden, weshalb ich empfehlen würde, grundsätzlich let und const zu verwenden.

Wann nun aber let und wann const? ;-)

Naja, der Sinn einer Konstante liegt im Wesentlichen darin, dass es aufgrund der für die gesamte Laufzeit des Programms (beziehungsweise Lebenszeit der Variablen) festgelegte Bindung von Bezeichner und Wert für den Interpreter möglich wird, bestimmte Optimierungen durchzuführen, um die Performanz des Programms zu verbessern.

Wenn also ein Wert hinterlegt werden soll und klar ist, dass die Variable diesen Wert behalten soll, dann verwende ich const. Ist es hingegen beabsichtigt, dass die Variable zu einem späteren Zeitpunkt einen anderen Wert zugewiesen bekommt, dann verwende ich let.

const object = {
  print ( ) {
    console.info(this.value);
  }
};

object.value = 42;

object.print( ); // 42

Schließlich handelt es sich bei der Verwendung von const auch um keine große Einschränkung, denn konstant ist hier tatsächlich nur die Bindung von Bezeichner und Wert, nicht aber der Wert selbst. Das heißt, wenn ein Objekt (und damit auch eine Funktion oder ein Array) als Wert einer Konstante hinterlegt wird, dann kann dieses nach wie vor verändert werden. Auch wenn dadurch vermutlich die Versuche zur Optimierung des Programms durch den Interpreter torpediert werden. ;-)

Hinterlässt document.body.className = list.includes(value) ? value : ''; bei nicht zutreffender Bedingung nicht unnötigerweise ein leeres Class-Attribut?

Das tut es. Aber du hattest die Änderungen ja nicht von der Präsenz des class-Attributes auf body abhängig gemacht, sondern von dessen Wert, weshalb es hier wohl ziemlich egal ist, ob das Attribut gesetzt bleibt oder nicht. Sonst kann man es aber natürlich mittels removeAttribute entfernen.

Viele Grüße,

Orlok

0 49

Regel in CSS Klasse ändern

Blumentopf
  • css
  • javascript
  1. 1
    Auge
    1. 0
      Gunnar Bittersmann
  2. 0
    Matthias Apsel
    • css
    • jsp
    1. 0
      Auge
      • css
      • javascript
      1. 0
        Matthias Apsel
        1. 0
          Auge
          • sprache
    2. 0
      Matthias Apsel
      1. 0
        Gunnar Bittersmann
        • css
        1. 0
          Matthias Apsel
          1. 0
            Gunnar Bittersmann
  3. 0
    Blumentopf
    1. 0
      Auge
      • css
      • html
      • javascript
      1. 0
        Blumentopf
        1. 0
          Auge
          1. 0
            Blumentopf
            1. 0
              Matthias Apsel
            2. 0
              Auge
              1. 0
                Blumentopf
              2. 0
                Orlok
                1. 0
                  Auge
                  1. 0

                    "Funktion" im Alltag

                    Der Martin
                    • sonstiges
                    1. 0
                      Auge
                      • menschelei
                      • sonstiges
                      1. 0
                        Der Martin
                        1. 0
                          Auge
                          1. 0
                            Der Martin
                    2. 0
                      Tabellenkalk
                      1. 0
                        Der Martin
                    3. 0
                      Der Martin
                      1. 1
                        JürgenB
                        • menschelei
                        • sonstiges
                        1. 0
                          Der Martin
                          1. 0
                            JürgenB
                            1. 0
                              Der Martin
                  2. 4

                    Arraymethoden und anonyme Funktionen

                    Orlok
                    • javascript
                  3. 2

                    const let var

                    Orlok
                    • javascript
                    1. 3
                      Orlok
                    2. 0
                      Auge
                      1. 1

                        Konstanten

                        Orlok
                        • javascript
                        • php
                        1. 0
                          Auge
    2. 0
      Gunnar Bittersmann
      • css
      • internationalisierung
      • javascript
      1. 0
        Gunnar Bittersmann
      2. 0
        Blumentopf
        1. 0
          Der Martin
          1. 0
            Blumentopf
            1. 0
              Der Martin
        2. 0
          Matthias Apsel
          1. 0
            Blumentopf
            1. 0
              Matthias Apsel
        3. 0
          Gunnar Bittersmann