Homepage de.comp.lang.javascript
Homepage
de.comp.lang.javascript

FAQ de.comp.lang.javascript

FAQ
de.comp.lang.javascript

 

 

Bitte verwenden Sie als Einstiegsadresse in diese FAQ die Homepage der Newsgroup de.comp.lang.javascript. Der Aufenthaltsort dieser Seiten hier kann sich ohne Vorwarnung ändern.
 

 

Wie kann ich Fehler beim Zugriff auf Eigenschaften und Methoden vermeiden?

Möchte man auf eine Eigenschaft oder Methode eines Objekts zugreifen und dieses Objekt ist wider Erwarten nicht vorhanden, erzeugt man damit einen Skriptfehler. Die weitere Ausführung des Skripts wird dann abgebrochen und dem Benutzer wird mitunter eine unschöne Fehlermeldung präsentiert, wie "foo has no properties", "bar ist null oder kein Objekt", "baz is not convertible to Object" oder ähnlich.

Um dies zu vermeiden, prüft man sinnvollerweise auf die Existenz jedes Objekts, von dessen Existenz man nicht ganz sicher ausgehen kann, bevor man einen Zugriff auf seine Eigenschaften oder Methoden versucht. In diesem Artikel wird beschrieben, wie man das programmiertechnisch sinnvoll und einigermaßen kompakt lösen kann.

Nehmen wir als Beispiel eine Anweisung, wie sie in Dynamischem HTML recht häufig vorkommt. Die Hintergrundfarbe (backgroundColor) eines HTML-Elements soll damit auf schwarz ("#000000") gesetzt werden:

document.getElementById("foo").style.backgroundColor = "#000000";
    

Hier finden wir gleich drei Zugriffe auf Eigenschaften oder Methoden von Objekten, deren Existenz wir nicht als sicher voraussetzen dürfen:

  1. Die Methode getElementById() des document-Objekts ist in älteren, nicht zum W3C-DOM kompatiblen, Browsern nicht verfügbar.
  2. Ein Element mit der ID foo ist vielleicht nicht verfügbar, dann besäße der Rückgabewert von getElementById() (dieser wäre dann null) keinerlei Eigenschaften.
  3. Es ist – rein hypothetisch – denkbar, dass getElementById() zwar ein von null verschiedenes Objekt zurückgäbe, dieses jedoch aus irgendwelchen Gründen gar keine Eigenschaft style besäße.

Um Fehler auszuschließen, müssen wir also auf die Existenz dieser drei Objekte testen. Hierbei machen wir uns zunutze, dass JavaScript es uns erlaubt, einfach das zu prüfenden Objekt als Ausdruck in einer if-Anweisung zu verwenden, um grob zu prüfen, ob der Ausdruck denn das gewünschte Objekt tatsächlich referenziert oder nicht 1):

if (document.getElementById) {
  if (document.getElementById("foo")) {
    if (document.getElementById("foo").style) {
      document.getElementById("foo").style.backgroundColor = "#000000";
    }
  }
}
    

Dabei muss nun der Interpreter gleich dreimal denselben Ausdruck document.getElementById("foo") auswerten. Um dies zu ersparen, weisen wir den dazugehörigen Wert einer Hilfsvariablen oElement zu:

var oElement;
if (document.getElementById) {
  oElement = document.getElementById("foo");
  if (oElement) {
    if (oElement.style) {
      oElement.style.backgroundColor = "#000000";
    }
  }
}
    

Dieselbe Vereinfachung 2) nehmen wir nun für das zweimal vorkommende oElement.style vor, als Hilfsvariable dient hier oStyle:

var oElement, oStyle;
if (document.getElementById) {
  oElement = document.getElementById("foo");
  if (oElement) {
    oStyle = oElement.style;
    if (oStyle) {
      oStyle.backgroundColor = "#000000";
    }
  }
}
    

Um dies nun weiter zu vereinfachen, machen wir uns zunutze, dass in JavaScript der Wert einer Wertzuweisung (mit dem Operator "=") gleich dem zugewiesenen Wert ist. Wir können daher die beiden Zuweisungen zu den Hilfsvariablen einfach als Ausdruck der if-Anweisungen notieren 3):


var oElement, oStyle;
if (document.getElementById) {
  if ((oElement = document.getElementById("foo"))) {
    if ((oStyle = oElement.style)) {
      oStyle.backgroundColor = "#000000";
    }
  }
}
    

Wollen wir jeden der drei Umstände "document.getElementById nicht vorhanden", "Element mit der ID foo nicht vorhanden" und "Eigenschaft style nicht vorhanden" gesondert behandeln, fügen wir an jede der drei if-Anweisungen noch einen else-Zweig mit der entsprechenden Fehlerbehandlung an. Ansonsten verwenden wir zuletzt zur weiteren Vereinfachung noch den logischen UND-Operator "&&", um die drei if-Anweisungen zu einer einzigen zusammenzufassen 4):

var oElement, oStyle;
if (document.getElementById
    && (oElement = document.getElementById("foo"))
    && (oStyle = oElement.style)) {
  oStyle.backgroundColor = "#000000";
}
    

Das ist nun zwar immer noch deutlich länger als der ursprüngliche Einzeiler, jedoch stellt es eine kurze und kompakte Möglichkeit ohne überflüssige mehrfache Referenzierungen dar, die oben beschriebene Fehlerquelle zu umgehen. Ein weiteres Beispiel: Aus dem fehlerträchtigen

document.forms["foo"].elements["bar"].value = 42;
    

wird auf gleiche Weise das sichere

var myForm, myElement;
if (document.forms
    && (myForm = document.forms["foo"])
    && (myElement = myForm.elements["bar"])) {
  myElement.value = 42;
}
    

Auch, wenn das zunächst etwas kompliziert aussieht: wenn man das erst ein paarmal so notiert hat, geht es sehr leicht von der Hand, da das Vorgehen ganz grundsätzlich immer dasselbe ist.

 

Anmerkungen

  1. Eigentlich prüfen wir so lediglich, ob der Ausdruck eine vorhandene Eigenschaft irgendeines vorhandenen Objekts mit einem Wert ungleich null, undefined, 0 oder false referenziert, denn als Ausdruck in einer if-Anweisung (also in einem booleschen Kontext) werden in JavaScript aufgrund dessen "lockerer" Typisierung die vier genannten Werte als boolescher Wert false, alle anderen Werte hingegen als boolescher Wert true interpretiert.
  2. Für das zweimal auszuwertende document.getElementById kann man diese Vereinfachung in manchen Browsern leider nicht vornehmen, weshalb wir dies so belassen müssen.
  3. Hierbei ist wichtig, dass wir die Zuweisungsanweisung nochmals in Klammern notieren, da manche Browser sonst eine Warnung wegen der Verwechslungsgefahr des Zuweisungsoperators "=" mit dem in if-Anweisungen sehr viel häufiger benötigten Vergleichsoperator "==" meldeten. Statt: if (a=b) ... müssen wir notieren: if ((a=b))....
  4. Hilfreich dabei ist, dass JavaScript sogenannte Minimal Evaluation (oder Short Circuit Evaluation) implementiert: wenn a einen der Werte false, null, 0 oder undefined liefert, wird b in einem Ausdruck a && b gar nicht mehr ausgewertet.
top

Diese Seite ist Teil der de.comp.lang.javascript FAQ. Die Einstiegsadresse lautet http://www.dcljs.de/. Der Text der Seite wurde erstellt von Dietmar Meier (©).

 ______ letzte Änderung: 12/2012 ______ 

 
© S. Mintert, Ch. Kühnel