Fork me on GitHub

Web Development

Ein Lehrbuch für das Informatik oder Medien-Informatik Studium.

Wie kann man Javascript-Code in größere Einheiten organisieren? Wo doch die Sprache keine Unterstütztung für Namespaces oder Kapselung bietet?

Eine Lösung für diese Fragestellung ist der Modul-Pattern, hier beschrieben nach Stefanov(2010): Javascript Patterns, Kapitel 5. Siehe auch Osmani(2012): Learning JavaScript Design Patterns.

Viele Skripte, ein Namensraum

Häuft werden in einer Webseite Javascript-Programm aus verschiedenen Quellen kombiniert. Die Webseite enthält z.B.

  • Javascript der Website selbst, zu Prüfung von Formulardaten und für Animationen
  • für Zugriffs-Statistiken, z.B. Google Analytics
  • für das Teilen von Inhalten auf Sozialen Netzwerkden, z.B. Facebook-Like-Button
  • für Feedback zu Webseite z.B. UserVoice
  • für Kommentare auf der Webseite, z.B. Disqus
  • für das Einbinden einer Landkarte, z.B. mit Leaflet oder Openlayers

Mit ein bisschen Copy-und-Paste kann man die verschiedenen Programme schnell in die eigene Webseite einbauen. All diese Programme laufen dann im selben Javascript Interpreter ab, und benutzen einen gemeinsamen globalen Namensraum.

Namensraum imitieren

Um einen Namensraum zu imitieren kann man ein Objekt in Javascript verwenden.

Die linke Version erzeugt 5 globale Namen. Oder, um genauer zu sein: sie erzeugt 3 Eigenschaften und 2 Methoden des window-Objekts. Würde ein anderes Programm ebenfalls ein Funktion f() definieren, so würde die spätere Definition erhalten bleiben.

In der rechten Version wird nur ein globaler Name angelegt: APP. Alle weiteren Namen sind dann in diesem Objekt versteckt. Würde ein anderes Programm in der Webseite auch eine Funktion f() definieren dann wäre das kein Problem mehr.

Javascript Code Ein globales Namensraum-Objekt statt vieler globalen Variablen

// globale Variabeln 

var KONSTANTE = 3.141;
var variable = 3;
function Ding(){
  return this;
}
function f(x){
  return 2*x;
}

var objekt = new Ding();
// ein Namensraum-Objekt
var APP = {}
APP.KONSTANTE = 3.141;
APP.variable = 3;
APP.Ding = function() {
  return this;
}
APP.f = function(x) {
  return 2*x;
}

APP.objekt = new APP.Ding();

Nachteile des Objekts als Namensraum

Wenn man modernes Javascript (z.B. ES6) oder ES5 mit “use strict” verwendet, dann erhält man Fehlermeldungen beim Zugriff auf nicht deklarierte Variablen.

Das Objekt als Namensraum kann das nicht bieten: ein nicht existierendes Attribut des Objekt liefert einfach den Wert undefined, aber keinen Fehler:

Kein Error im namensraum

Namensräume anlegen

Namensräume können auch verschachtelt werden:

Javascript Code Verschachtelte Namensräume

var GAME =  GAME || {};
GAME.Player = ...
GAME.Master = ...

Die erste Zeile enthält eine Vorsichtsmaßnahme: Falls GAME schon definiert wäre, dann wird die alten Definition nicht überschrieben. Dabei macht man sich die Kurzschulssauswertung des Oder-Operators zu nutze.

Folgender Code zeigt eine alternative Schreibweise für diese Zuweisung:

Javascript Code Schreibweisen für Default-Wert

var GAME = GAME || {};





var GAME;
if( GAME ) {
  // GAME = GAME;
} else {
  GAME = {};
}

Sofort ausgewertete Funktionen

Eine andere Methode um den globalen Namensraum sauber zu halten sind die sogenannten “sofort augewerteten Funktionen” (“immediately invoked funktion” oder “immediate function”).

Dabei wird eine Funktion definiert und sofort - und nur einmal - aufgerufen. Nur der Rückgabewert wird ein einer globalen Variable g gespeichert.

Beachten sie dabei die Klammern rund um die Funktions-Definition:

Javascript Code Schreibweise für sofort ausgewertete Funktionen

var g = (function(){
  return 42;
})();

Hier eine komplexere Version. Die vielen Variablen und Funktionen die innerhalb der sofort ausgewertete Funktion definiert sind, bleiben unsichtbar. Sie sind “von aussen” nicht zugänglich.

Javascript Code sofort ausgwertete Funktion

var g = (function(){
  var a,b,c;
  function d(x) {
    return 2*x;
  }
  function Ding(v) {
    this.value = v;
  }

  a = 10;
  b = d( a );
  c = new Ding(b);

  return a;
})();

Module

Namensräume und sofort augewertete Funktionen werden verwendet um sogenannte Module zu bauen. Das Modul bündelt alle Namen unter einem Namensraum und bietet die Möglichkeit von privaten und öffentlichen Eigenschaften und Funktionen.

In diesem Beispiel ist das Modul ein Objekt:

Javascript Code Schreibweise für ein Modul: ein Objekt

var APP = (function(){
  var a,b,f;      // private 
  var c,d,g;      // öffentlich
  f = function() {  
    // private Funktion
  };
  g = function() {  
    // öffentliche Funktion
  };
  return {
    c: c,
    d: d,  
    g: g
  };
})();

Siehe Auch