ECMAScript 5, die nächste Version von JavaScript – Teil 2: Der Strict Mode

Achtung: dieser Beitrag ist alt! Es kann gut sein, dass seine Inhalte nicht mehr aktuell sind.

Dass das alte Testament der modernen JavaScript-Community den Titel JavaScript: The Good Parts trägt, lässt erahnen, dass nicht alles in dieser Programmiersprache ganz problemfrei ist, also auch einiges an bad parts vorhanden ist. Diese werden von geübten Programmieren meist gemieden, stellen aber immer noch eine veritable Tretmine dar. Um diese problematischen „Features“ langsam gen Altenteil zu schieben, führt ES5 den Strict Mode ein, der eigentlich nichts weiter als ein Subset von „normalem“ JavaScript ist – alles Gute bleibt drin, alles Böse existiert im Strict Mode nicht mehr. Und wer weiter böse programmieren will, muss sich nicht fürchten, denn der Strict Mode ist ein Opt-In-Feature.

Was macht der Strict Mode?

Der Strict Mode ist ein bereinigtes JavaScript-Subset. Er führt nichts neues ein, entfernt aber einige problemtische Altlasten. Unter anderem wird

  • das unberechenbare with-Statement abgeschafft,
  • ein Fehler ausgelöst wenn man durch ein vergessenes var unbeabsichtigt eine globale Variable anlegt,
  • die Anzahl der befremdlichen Eigenheiten von this, eval() und arguments reduziert,
  • durch unsinnige Anweisungen wie NaN = 42 ein Fehler ausgelöst
  • und die oktale Syntax (0644 == 420) verboten.

JavaScript wird im Strict Mode also entrümpelt und vieles, was früher nur bad practice war, in einen handfesten Fehler, den ein Browser auch meldet. Es ist im Strict Mode einfach wesentlich schwieriger, schlechte Programme zu scheiben: Fehler werden sichtbarerer, die Quellen für solche Fehler werden weniger und der Programmierer kann sich mehr auf seine Aufgabe als auf die Besonderheiten seiner Programmiersprache konzentrieren.

Den Strict Mode auslösen

Strict Mode auszulösen ist einfach; man braucht nur "use strict"; an den Anfang einer Scriptdatei zu setzen:

"use strict";
x = "foo"; // ReferenceError - "var" vergessen

Das Ganze funktioniert auch auf Funktionsebene. Wer nicht komplette Scripts in den Strict Mode versetzen will, kann sich auf einzelne Funktionen beschränken:

var x = "Ich bin NICHT im Strict Mode!";

function foo(){
    "use strict";
    var y = "Ich BIN im Strict Mode!";
}

function bar(){
    var z = "Ich bin NICHT im Strict Mode!";
}

Der Strict Mode ist an den Funktionskontext gebunden. So wie innerhalb einer Funktion erstellte Funktionen auf die Variablen der äußeren Funktion Zugriff haben, so erben sie auch den Strict Mode:

var x = "Ich bin NICHT im Strict Mode!";

function foo(){
    "use strict";
    var y = "Ich BIN im Strict Mode!";
    return function(){
        var z = "Ich bin AUCH im Strict Mode!";
    }
}

Zu beachten ist, dass man den Strict Mode nicht auf einzelne If- oder Schleifen-Blöcke beschränken kann. Das Ganze funktioniert nur auf Script- oder Funktionsebene.

Strict-Mode-Scripts sind zu 100% abwärtskompatibel. Da für Browser, die den Strict Mode nicht kennen, "use strict"; nur ein beliebiger String, also ein JavaScript-Ausdruck ohne Bedeutung ist, verarbeitet auch der älteste Internet Explorer solche Scripts ohne zu murren – der Strict Mode definiert schließlich nichts weiter als ein Subset von „normalem“ JavaScript. Man kann also (theoretisch) ohne Probleme ab heute dazu übergehen, nur noch im Strict Mode zu programmieren, vorausgesetzt man testet seine Scripts vorher in mindestens einem Browser, der dieses ES5-Feature auch implementiert.

Die Auswirkungen des Strict Mode im Detail

Weniger globale Variablen: Erstellt man in normalem JavaScript eine neue Variable, ohne ihr var voranzustellen, macht man sie zu einer globalen Variable. Da dieser Effekt fast nie so gewollt ist (wer globale Variablen braucht, sollte sie auf der globalen Ebene mit var entsprechend deklarieren) und meist auf ein Vergessen des var zurückzuführen ist, hagelt es hierfür im Strict Mode Fehler. So kann man sich sicher sein, dass wenn am Ende des Tages das Programm keine Fehler wirft, man nirgends ein var vergessen hat.

"use strict";
x = 42; // ReferenceError - "var" fehlt

Mehr (sichtbare) Fehler: Es gibt in JavaScript viele Dinge, die man zwar ausdrücken kann, die aber nicht funktionieren. Es ist absolut möglich undefined = 42 in ein Script zu schreiben, doch einen Effekt hätte es (zum Glück) nicht – undefined ist (in ES5) schreibgeschützt. Damit man es aber auch mitbekommt, wenn man solcherlei Unsinn schreibt, wirft JavaScript im Strict Mode immer dort einen Fehler, wo es vorher nur stillschweigendes Nichtfunktionieren gab:

"use strict";
undefined = 42;          // TypeError - "undefined" kann nur undefined sein
delete Object.prototype; // TypeError - Object.prototype ist schreibgeschützt

Mehr Einzigartigkeit: Verwendet man in einer Funktion mehrere Argumente mit gleichem Namen oder versucht man, in einem Objektliteral mehrere gleichnamige Eigenschaften zu definieren, setzt es im Strict Mode einen Syntaxfehler. Nur so bemerkt man solche einfache Fehler sofort beim ersten Test, denn ohne Strict Mode würde einfach das jeweils letzte Argument bzw. die letzte Objekteigenschaft stillschweigend ihre Vorgänger überschreiben. Und so etwas zu debuggen kann richtig schwierig werden – schwieriger jedenfalls, als einfach die Syntaxfehler im Strict Mode zu finden und auszumerzen.

"use strict";
var o = { foo: "x", foo: "y" }; // SyntaxError - Zwei mal "foo" geht nicht
function foo(x, x, z){}         // SyntaxError - Zwei mal "x" geht nicht

Weniger WTF bei eval() und arguments:

Im Strict Mode sind eval und arguments (enthält in Funktionen alle Argumente dieser Funktion) reservierte Namen, die nicht überschrieben werden können. Das auf die aufrufende Funktion verweisende arguments.callee ist aufgrund seiner Arbeitsweise ein großes Hindernis für die Performanceoptimierung-Mechanismen in den Browsern und wird unter anderem deshalb abgeschafft. Außerdem sind die Argumente einer Funktion nicht mehr fest an arguments gebunden – arguments enthält im Strict Mode immer die Original-Werte, mit denen die Funktion ursprünglich aufgerufen wurde, Modifikationen werden nicht mehr übertragen:

function foo(x){
    x++;
    console.log(arguments[0]); // 43
}
foo(42);

function bar(x){
    "use strict";
    x++;
    console.log(arguments[0]); // 42 dank Strict Mode
}
bar(42);

Weniger WTF bei this: Bei Funktionsaufrufen wie foo(); ist in normalem JS this in der Funktion das globale Objekt. Wenn man in dieser Situation versucht, Methoden und Eigenschaften für this zu definieren (weil man sich zum Beispiel aufgrund eine Programmierfehlers fälschlicherweise im Methoden- oder Constuctorkontext wähnt), produziert man globale Variablen ‐ und zwar ohne es zu merken! Deshalb gilt im Strict Mode: this ist in Funktionsaufrufen undefined, so dass Irrtümer wie ein vergessenes new schneller auffallen – undefined kann man schließlich nicht mit neuen Eigenschaften oder Methoden versehen, ohne dass es Fehler hagelt.

Weniger Freiheiten bei Funktionsstatements: Funktionsstatements wie function foo(){} erlauben moderne Browser an so ziemlich jeder Stelle im Code, kommen aber in If-Blöcken oder Schleifen zu sehr unterschiedlichen Ergebnissen bei der Auswertung dieser Statements. Um dieses Problem in aus dem Weg zu räumen, dürfen im Strict Mode Funktionsstatements nur noch direkt in einem Script oder einer Funktion stehen, nicht innerhalb von If-Blöcken oder Schleifen:

"use strict";
if(true){
    function foo(){} // SyntaxError
}

function bar(){}     // Kein Problem

Weniger with-Statement: Niemand sollte je das with-Statement verwenden, also verbietet es der Strict Mode und erklärt es zu einem Syntaxfehler.

Weniger oktale Syntax: Alle Browser interpretieren Zahlen mit vorangestellter Null als Oktalzahl (0644 == 420) – und das, obwohl es gar nicht im ECMAScript-Standard vorgeschrieben ist. Da Oktalzahlen selten nützlich und oft verwirrend sind, sind sie im Strict Mode verboten und produzieren einen Syntaxfehler.

Mehr reservierte Wörter: implements, interface, let, package, private, protected, public, static, und yield sind im Strict Mode reservierte Namen für zukünftige ECMAScript-Versionen und können nicht mehr als Variablennamen u.Ä. verwendet werden:

"use strict";
var package = 42; // package is a reserved identifier

Fazit und Fallen

Der Strict Mode ist nicht viel mehr, als ein um einige Fallen bereinigtes JavaScript. Da er ein Subset von „normalem“ JavaScript darstellt sollten Strict-Mode-Scripts problemlos in jedem modernen und unmodernen Browser funktionieren. Neu ist eigentlich nur, dass man im Strict Mode so programmiert, als würde einem ständig Douglas Crockford über die Schulter schauen.

Die einzig große Falle könnte dann zuschnappen, wenn performancebedingt mehrere JS-Dateien zusammenfügt werden; ist nur ein einziges Strict-Mode-Script dabei, wird der gesamte Code nach den strengen Regeln ausgewertet, was, wenn nicht alle Scripts hierfür vorbereitet sind, übel enden könnte. Als Vorsichtsmaßnahme kann man, wenn man es nicht ohnehin schon macht, seine Scripts in eine sofort ausgeführten Funktion kapseln. So kann man sich sicher sein, dass der Strict Mode immer auf das eigene Script beschränkt bleibt:

(function(){
    "use strict";
    // Code
})()

Sollte man schon heute den Strict Mode verwenden? Schwierige Frage. Einerseits müsste, wie bereits erwähnt, jeder Browser Strict-Mode-Code ausführen – nur wird eben nicht jeder Browser die diversen Neuheiten durchsetzen. Da es aber zu Zeit mit dem Firefox 4 nur einen einzigen Browser gibt, der den Strict Mode (vollständig) implementiert, hat man als Webentwickler nur diesen einen Browser als Testplattform zur Verfügung. Und nun stelle man sich vor, es gäbe einen Bug im Strict Mode des Firefox 4, der Code, der eigentlich Fehler auslösen müsste, passieren lässt – und dann updaten eines Tages alle anderen Browserhersteller ihre Produkte mit einem korrekten Strict Mode und das nur im Firefox getestete Script funktioniert nicht mehr …

Für den Moment ist es vielleicht nicht die schlechteste Idee, Scripts im Strict Mode zu entwickeln, das "use strict"; aber zu entfernen bevor man den Code in die freie Wildbahn loslässt. So nutzt man beim Programmieren alle Vorteile, hat aber am Ende mit absoluter Sicherheit ein funktionierendes Programm – und das ist ja auch nicht ganz unwichtig.

Kommentare (14)

  1. Holger

    12. April 2011, 09:20 Uhr

    Vielen Dank für die ausführliche und verständliche Zusammenfassung der Neuerungen in ES5.

  2. molily

    12. April 2011, 10:32 Uhr

    Chromium- und WebKit-Nightlies implementieren den Strict Mode auch schon weitesgehend, sodass man zumindest einen Vergleich auf Basis von Beta-Versionen hat, wenn Firefox 4 sich seltsam verhält.

  3. Nico

    12. April 2011, 11:09 Uhr

    Hat der strict-Modus nun Einfluss auf die Ausführung eines Codes? Anders gefragt: Würde ein gleiches Stück Code, das im strict-Modus keine Fehler wirft, im strict-Modus und im normalen Modus zum gleichen Ergebnis führen? Wenn ich deinen letzten Absatz richtig verstanden habe, ist dem ja so, oder nicht?

  4. Ole

    12. April 2011, 12:07 Uhr

    Hey,

    Danke fuer diesen wirklich sehr guten Artikel Peter!

    Eine frage bleibt bei mir allerdings noch offen, wie verhaelt es sich bei inline JavaScript, reicht einmal pro Seite oder doch pro script tag?

    LG

  5. Peter

    12. April 2011, 17:30 Uhr

    Einmal reicht.

  6. Peter

    12. April 2011, 17:32 Uhr

    Zitat Nico:

    Hat der strict-Modus nun Einfluss auf die Ausführung eines Codes? Anders gefragt: Würde ein gleiches Stück Code, das im strict-Modus keine Fehler wirft, im strict-Modus und im normalen Modus zum gleichen Ergebnis führen? Wenn ich deinen letzten Absatz richtig verstanden habe, ist dem ja so, oder nicht?

    Das Ergebnis wird das gleiche sein, aber die Ausführung kann sich in sofern ändern, als dass die Browser durch den Wegfall von with und arguments.callee die Performance besser optimieren können.

  7. Chris

    12. April 2011, 18:33 Uhr

    Schöner Beitrag, sehr aufschlussreich.

    Wann kommt endlich dein erstes Buch zu JavaScript-Grundlagen? Dann würde ich mir die Sprache ja doch mal ausführlich antun … ;-)

  8. Peter

    13. April 2011, 07:26 Uhr

  9. Sacha

    13. April 2011, 15:10 Uhr

    Douglas Crockford schaut uns doch via JSLint eh schon dauern über die Schulter! ;)

  10. realityking

    14. Juli 2011, 18:35 Uhr

    Das stimmt so nicht ganz, ein script was, im strict mode geschrieben, sich darauf verlässt, dass sich arguments nicht verändert wird nicht mehr korrekt funktionieren wenn es ohne strict mode ausgeführt wird. Man sollte also sehr vorsichtig sein heute schon scripte im strict mode zu schreiben.

  11. Peter

    14. Juli 2011, 19:07 Uhr

    Beispiel?

  12. realityking

    14. Juli 2011, 19:12 Uhr

    Hast du schon selbst im Abschnitt "Weniger WTF bei eval() und arguments" geliefert.

  13. Peter

    14. Juli 2011, 19:19 Uhr

    Ah so, jetzt verstehe ich deinen Kommentar. Was ich nicht verstehe ist, worauf du hinaus möchtest. Strict-JS ist logischerweise ein Subset von Normal-JS und nicht umgekehrt, dass manche alte Technik in der neuen Welt nicht mehr funktioniert, ist doch eigentlich nur folgerichtig.

  14. realityking

    14. Juli 2011, 19:34 Uhr

    Das Problem entsteht wenn ich mein script mit "use strict"; in einem Browser der das unterstützt entwickle und dabei arguments so benutze das ich mich darauf verlasse das sich der Wert nicht verändert, im schlimmsten Fall nur in einem Randbereich.

    Wenn ich mich jetzt auf den - oft vertretenen - Standpunkt stelle, dass non strict JS ist ein superset von strict JS ist. Da her dass es mich nur vor schlechtem code schützt aber wenn alles mit strict funktioniert, funktioniert es immer noch ohne strict.

    Das ist aber hier genau nicht der Fall, wenn ich so programmiere funktioniert mein script in non strict browsern aber nicht mehr (richtig). Deswegen würde ich den strict mode (derzeit) nur intern zum testen benutzen und sehr sehr vorsichtig sein den strict mode auf einer öffentlichen webseite zu benutzen.

    Ein wenig googlen fördert zutage, dass die Mozilla Dokumentation mir zustimmt.

    Browsers not supporting strict mode will run strict mode code with different behavior from browsers that do, so don't rely on strict mode without feature-testing for support for the relevant aspects of strict mode.

    Browsers don't reliably implement strict mode yet, so don't blindly depend on it. Strict mode changes semantics. Relying on those changes will cause mistakes and errors in browsers which don't implement strict mode. Exercise caution in using strict mode, and back up reliance on strict mode with feature tests that check whether relevant parts of strict mode are implemented. Finally, make sure to test your code in browsers that do and don't support strict mode. If you test only in browsers that don't support strict mode, you're very likely to have problems in browsers that do, and vice versa.

Die Kommentarfunktion ist seit Juli 2014 deaktiviert, weil sie zu sehr von Suchmaschinenoptimierern für manuellen Spam mißbraucht wurde. Wenn du Anmerkungen oder Fragen zum Artikel hast, schreib mir eine E-Mail oder melde dich via Twitter.

Folgt mir!

Kauft mein Zeug!

Cover der HTML5-DVD
Infos auf html5-dvd.de, kaufen bei Amazon

Cover des HTML5-Buchs
Infos auf html5-buch.de, kaufen bei Amazon

Cover des CSS3-Buchs
Infos auf css3-buch.de, kaufen bei Amazon