JavaScript/strict mode

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

In JavaScript gibt es aufgrund der bewegten Geschichte mit vielen proprietären Methoden und der sehr einfachen Möglichkeit, globale Variablen einzuführen, viele potentielle Fehlerquellen. Deshalb wurde mit ECMA5 der Strenge Modus (strict mode) eingeführt, der ein standardisiertes, um Fehlerquellen bereinigtes, Subset der Programmiersprache aktiviert. Die Arbeitsweise von JavaScript außerhalb des strengen Modus bezeichnet man salopp auch als sloppy mode (schlampig, schluderig).

Aktivierung des strict mode

Der strenge Modus lässt sich für ein komplettes Script-Element oder nur für einzelne Funktionen aktivieren. Dazu ist zu Beginn das merkwürdig aussehende Statement 'use strict'; zu notieren.

strict mode auf Script-Ebene
'use strict';
x = 42;

Normalerweise würde aus dieser Zuweisung eine globale Variable entstehen, die dann in anderen Teilen des Programms zu unerwünschten Konsequenzen führen kann.

Durch die Angabe von 'use strict'; wissen die Browser, dass sie einen strengeren Maßstab anlegen müssen und lösen eine Fehlerbedingung (ReferenceError) aus, da die Variable nicht deklariert ist. Ältere Browser sehen in 'use strict'; nur einen reinen String, den sie ignorieren (formal ist es so, dass ein Ausdruck ein gültiges Statement darstellt. Eine Konstante ist die einfachste Form eines Ausdrucks).

Empfehlung: Verwenden Sie immer den Strengen Modus mit 'use strict';! Deklarieren Sie globale Variablen am Anfang des Scripts mit var oder const (wenn sie sich nicht mehr verändert)!

Wenn Sie nicht komplette Programme in den Strengen Modus versetzen wollen, können Sie ihn nur auf einzelne Funktionen beschränken:

strict mode auf Funktionsebene
// Hier besteht kein strict mode, die Zuweisung erzeugt eine globale Variable
x = 42;

// Zuweisung an undeklarierte Variable innerhalb einer Funktion im Strict Mode
function zuweisungStrict(){
    'use strict';
    name = "Arthur Dent";        
}

zuweisungStrict();      // Löst einen ReferenceError aus

Achtung!

An zwei Stellen verwendet JavaScript den strengen Modus automatisch:
  • In ECMAScript-Modulen (eingebunden mit <script type="module">)
  • In Klassen, die mit dem class-Schlüsselwort deklariert wurden

Auswirkungen des strict mode

Variablen müssen deklariert werden

Zuweisungen ohne var werden in JavaScript (wie im oberen Codebeispiel) zu globalen Variablen. Auch ein reiner Tippfehler führt zu einer neuen globalen Variable:

globale Variable durch Tippfehler
var variableX = 42;            // Zuweisung als globale Variable


function zuweisungZahl() {
    variabelX = prompt("Geben Sie eine neue Zahl ein", "");
}

Durch die falsche Schreibweise von variableX wird der Wert nicht überschrieben, sondern eine neue globale Variable angelegt.

Im 'strict mode' würde es einen 'ReferenceError' geben.

Globale Variablen können später unerwünschte Konsequenzen auslösen.

  • Gleich benannte globale Variablen unterschiedlicher Scripte überschreiben sich gegenseitig
  • Ein Tippfehler beim Programmieren kann unbemerkt eine neue Variable erzeugen, während die eigentlich gemeinte Variable leer bleibt

Da solche keine Syntaxfehler sind, kann man sie nur sehr schwer debuggen.

Fehler werden sichtbar

JavaScript war als anfängerfreundliche Sprache konzipiert, die bei Fehlern nicht sofort abbrechen sollte. So werden bei einigen Programmierfehlern (mistakes) die Fehlermeldungen unterdrückt. Während dies manchmal einen Abbruch des Programms verhindert, entstehen teilweise schwerwiegendere Fehler (error), die erst später sichtbar werden, wenn das Programm unerwartet abbricht. Zu diesem Zeitpunkt ist dann oft nicht mehr ersichtlich, welcher mistake ursprünglich verantwortlich war.

Im strict mode werden Meldungen für diese Fehler in der Konsole ausgegeben. So können Sie diese Fehler während des Entwickelns und Debuggens identifizieren, analysieren und beseitigen.


arguments

Beim Aufruf einer Funktion wird ein spezielles Objekt arguments erzeugt, das die Argumente der Funktion wie in einem array speichert.

Arguments
function foo() {
  bar(1, 2);
}

function bar(arg1, arg2) {
  var temp = arguments[0];
  arguments[0] = arg2;
  arguments[1] = temp;
  alert(arg1 + " " + arg2);
}

In diesem Beispiel haben arguments[0] und arg1 sowie arguments[1] und arg2 die gleichen Werte. Normalerweise wird bei der Änderung eines Werts der andere ebenfalls verändert. In der Funktion bar werden die Werte von arg1 und arg2 getauscht, obwohl nur die Werte des arguments-Array verändert wurden.

Im strikten Modus ist dies nicht erlaubt; die Werte von arg1 und arg2 bleiben unverändert.


Das arguments-Objekt enthält auch einen Zeiger auf die gerade ausgeführte Funktion. Mit arguments.callee können Sie die Funktion referenzieren. Dies ist innerhalb von anonymen Funktionen sinnvoll, bei anderen Funktionen können Sie die Funktion mit ihrem Namen aufrufen.

Im strikten Modus ist der Aufruf von arguments.caller und arguments.callee nicht erlaubt.

Funktionsaufrufe

In JavaScript können Sie auch innerhalb von Block-Anweisungen Funktionsdeklarationen notieren. Sie werden unabhängig davon, wo sie im Quelltext stehen, gleich zu Beginn geparst und interpretiert. Das kann in manchen Fällen zu unerwartetem Verhalten führen.

Beispiel
if (true) {
  function foo () {
    return 'first';
  }
} else {
  function foo () {
    return 'second';
  }
}
foo(); // Manche Javascript-Engines führen die erste Funktion aus, manche die zweite.

Im strikten Modus gelten die Funktionsdeklarationen nur innerhalb ihres Anweisungsblocks. Der Aufruf von foo() außerhalb dieser Blocks bricht der Meldung ab, dass foo nicht definiert sei.

Um dennoch Funktionen erstellen zu können, deren Implementierung von einer Bedingungen abhängig ist, können Sie eine Variable anlegen und ihr nach Bedarf eine anonyme Funktion zuweisen:

Beispiel
'use strict';
var foo;
if (true) {
  foo = function () {
    return 'first';
  };
} else {
  foo = function () {
    return 'second';
  };
}
foo(); // Jede Javascript-Engine führt die erste Funktion aus.


this

Wird eine Funktion normal aufgerufen (d.h. nicht als Methode), enthält this außerhalb des strict mode das globale Objekt. Dieses Verhalten wurde früher oft genutzt, um sich in Programmen, die nicht nur im Browser ausgeführt werden sollen, eine Referenz auf das globale Objekt zu verschaffen.

Im strict mode enthält this in solchen Funktionsaufrufen den Wert undefined. Verwenden Sie die neue globale Variable globalThis, die im Browser, in Workern und auch in node.js definiert ist, um auf das globale Objekt zuzugreifen. Vermeiden Sie außerdem, Variablen mit den Namen window, self, global oder globalThis zu definieren, weil diese Namen in verschiedenen Ausführungskontexten den Zugriff auf das globale Objekt bereitstellen. Wenn Sie sie für eigene Zwecke verwenden, können Sie den Zugriff auf das globale Objekt versperren.

with

Mit dem with-Statement konnten Sie mehrere Anweisungen in Folge notieren, die alle mit dem gleichen Objekt arbeiten.

Beispiel
    with (document) {
      open();
      write("<p>Diese Seite hat den Titel " + title + "<\/p>");
      close();
    }

Da normalerweise mehrere Anweisungen folgen, die dieses Objekt verwenden, müssen Sie alle diese Anweisungen in geschweifte Klammern einschließen.

Achtung!

Vermeiden Sie das with-Statement, da es den Code schwerer lesbar macht und so ein Zurückverfolgen von Fehlern erschwert!
Im strict mode ist das with-Statement verboten und erzeugt einen Syntaxfehler![1]

Empfehlungen für die Praxis

Empfehlung: Verwenden Sie 'use strict';!

'use strict'; führt dazu, dass Programmierer ...

  • Fehler beim Entwickeln früher erkennen
  • Scripts leichter debuggen können
  • sich mehr Gedanken um den Geltungsbereich von Variablen machen
  • letztendlich eine bessere Strukturierung und Kapselung der Scripts erreichen

Dieser Zwang zu mehr Disziplin ist insbesondere dann wichtig, wenn Code aus der Hand gegeben oder in Teamarbeit entwickelt wird.

Peter Kroener empfiehlt, 'use strict'; beim Entwickeln zu verwenden und dann zu entfernen, um ältere Browser (und künftige Bugs) zu berücksichtigen. Allerdings setzt dies voraus, in der Programmierung auf Methoden, die im strengen Modus anders arbeiten, zu verzichten.[2]

Weblinks

  1. yuiblog.com: With statement considered harmful
  2. Peter Kröner: Der Strict mode