Thema dieser Seite

Ich habe meine ersten Schritte in JavaScript in etwa im Jahr 2000 gemacht. Seitdem hat sich die Sprache immens weiterentwickelt und sie wird inzwischen auch für Server-seitige Anwendungen wie bei Node.js oder für Plugins bei Anwendungen wie Atom verwendet.

Da ich vermehrt Anwendungen lediglich mit JavaScript Code umsetze, bin ich auf der Suche nach einem Programmierstil, der eine einfache Wartbarkeit und am besten auch eine gute Kapselung von Funktionalitäten ermöglicht.

Diese Seite soll eine Sammlung von Tipps werden, die mir für dieses Ziel hilfreich erscheinen.

Wie ich allerdings objektorientiert mit Javascript programmiere, habe ich auf der Seite Objektorientiertes Programmieren in Javascript mit functions zusammengefasst.

Die Tipps sind natürlich nicht auf meinem Mist gewachsen. Im Endeffekt habe ich im Internet gesucht und die Techniken, die mir hilfreich erschienen, auf diese Seite übernommen. Die Quellen trage ich in dieser Liste zusammen:

Meine empfohlenen Best Practices für JavaScript

Verwendung von const

Wenn man Konstanten definiert, so sollten sie immer mit const deklariert und sofort initiiert werden. Damit kommt es zu Fehlern, wenn sie unabsichtlich überschrieben werden. Außerdem sollten die Namen von Konstanten lediglich mit Großbuchstaben und Unterstrichen erfolgen. Konstanten gelten für den Scope (z.B. Funktionsblock) für den sie definiert wurden.

Wie es funktioniert zeigt für mich am besten folgender Funktionsblock, den ich von der Dokumentation MDN web docs - const kopiert habe:

       // HINWEIS: Konstanten können sowohl mit Klein- als auch Grossbuchstaben deklariert
       // werden. Üblicherweise verwendet man aber lediglich Grossbuchstaben als Bezeichner für Konstanten.

       // Definiert my_fav als eine Konstante und weist ihr den Wert 7 zu.
       const MY_FAV = 7;

       // Ein Versuch, der Konstanten einen anderen Wert zuzuweisen, ergibt
       // einen Fehler.
       MY_FAV = 20;

       // Schreibt 7 auf die Konsole.
       console.log("my favorite number is: " + MY_FAV);

       // Der Versuch, eine existierende Konstante neu zu definieren,
       // erzeugt einen Fehler
       const MY_FAV = 20;

       // Der Name my_fav ist für die obige Konstante reserviert, weshalb
       // dieses ebenfalls einen Fehler erzeugt.
       var MY_FAV = 20;

       // Auch dies ergibt einen Fehler.
       let MY_FAV = 20;

       // Man beachte, dass const Deklarationen auf Blöcke begrenzt sind.
       if (MY_FAV === 7) {
           // Dies funktioniert und erzeugt eine neue Konstante MY_FAV innerhalb
           // des aktuellen Blocks. (Es liesse sich auch mit let eine Variable deklarieren.)
           const MY_FAV = 20;

           // MY_FAV ist nun 20
           console.log("my favorite number is " + MY_FAV);

           // Diese Variable hingegen wird in den globalen Kontext gehoisted und ergibt einen Fehler
           var MY_FAV = 20;
       }

       // MY_FAV ist immer noch 7
       console.log("my favorite number is " + MY_FAV);

       // Konstanten benötigten einen Initialwert, weshalb hier ein SyntaxError
       // erzeugt wird.
       const FOO;

       // Konstanten können auch Objekte sein.
       const MY_OBJECT = {"key": "value"};

       // Ein Versuch, der Konstanten ein anderes Objekt zuzuweisen, ergibt
       // einen Fehler.
       MY_OBJECT = {"OTHER_KEY": "value"};

       // Das Objekt selber hingegen ist nicht vor Veränderungen geschützt.
       // Das folgende Statement wird ohne Probleme ausgeführt.
       MY_OBJECT.key = "otherValue"; // Verwerde Object.freeze() um ein Objekt unveränderbar zu machen

       // Das Gleiche gilt für Arrays
       const MY_ARRAY = [];
       // Es ist möglich, neue Einträge an das array anzufügen.
       MY_ARRAY.push("A"); // ["A"]
       // Jedoch der Versuch, der Konstanten ein anderes Array zuzuweisen,
       // ergibt einen Fehler.
       MY_ARRAY = ["B"]
           

Daraus ergeben sich folgende Vorteile:

Verwendung von let

Mit let werden Variablen nur für den aktuellen Code-Block definiert. Man sollte daher alle lokalen Variablen, die nur für die aktuelle Schleife, Funktion oder if-Block in Verwendung sind, immer mit let deklarieren und sofort auch einen Wert zuweisen.

Wendet man let nicht im Rahmen eines Blocks an (also in der ersten Ebene eines Programms), dann bleibt der Wert der definierten Variable undefined. Die Variable ist also nicht angelegt.

Lässt man let weg, so wird die Variable an den globalen Scope angehängt und ist überall sichtbar.

Verwendet man var, so ist der Gültigkeitsbereich der Variable die umschließende Funktion. Der folgende Code, den ich von der Dokumentation MDN web docs - let kopiert habe, beschreibt den Unterschied sehr gut.

            function varTest() {
              var x = 31;
              if (true) {
                var x = 71;  // gleiche Variable!
                console.log(x);  // 71
              }
              console.log(x);  // 71
            }

            function letTest() {
              let x = 31;
              if (true) {
                let x = 71;  // andere variable
                console.log(x);  // 71
              }
              console.log(x);  // 31
            }
          

Die Verwendung von let führt zu folgenden Vorteilen:

Überladen von functions mit Default-Parameter-Settings

Aus anderen Programmiersprachen wie beispielsweise Java kennt man das Konzept, dass man Methoden überladen kann. Das heißt man hat im Prinzip zwei Methoden des selben Namens, aber mit unterschiedlichen Parametern.

Im folgenden ein Java-Beispiel:

    public void drawLine(int x1, int y1, int x2, int y2, Color color) {
      //draw line commands
    }

    public void drawLine(int x1, int y1, int x2, int y2) {
      drawLine(x1, y1, x2, y2, Color.BLACK);
    }
  

In JavaScript gibt es Probleme, wenn zwei functions im selben Scope gleich benannt werden. In diesem Fall kann man sich aber darüber hinweghelfen, dass man dem letzten Parameter, der Farbe, einen Default-Wert gibt.

    function drawLine(x1, y1, x2, y2, color = 'rgb(0, 0, 0)') {
      //do stuff here
    }
  

Somit kann der Wert beim Aufruf weggelassen werden:

    drawLine(0, 0, 100, 100); //black line
    drawLine(0, 0, 100, 100, 'rgb(255,0,0)'); //red line