JavaScript/Tutorials/OOP/Objektabfrage
Informationen zum Autor
- Name:
- Mathias Schäfer
- E-Mail:
- molily@mailbox.org
Inhaltsverzeichnis
Zeitgemäße JavaScript sollen robust und browserübergreifend funktionieren, mit anderen Scripten problemlos zusammenarbeiten und unter Umständen von fremden Entwicklern angesteuert werden. Bis vor einiger Zeit wurden zu diesem Zweck zuhauf zweifelhafte »Browserweichen« eingesetzt, die z. B. mithilfe von des navigator-Objektes versuchten, den Browser anhand seines Namens zu identifizieren. Diese Erkennung wurde dann verwendet, um indirekt auf die Fähigkeiten des Browsers zu schließen.
Dieser Weg ist in der heutigen Weblandschaft, in der die Browser in ihren verschiedenen Versionen unzählige Techniken unterschiedlich umsetzen, nicht mehr gangbar. Der Browsermarkt und die Entwicklung neuer, in JavaScript nutzbarer Techniken ist zu stark in Bewegung, als dass eine solche »Browserweiche« zuverlässig und zukunftsfähig sein könnte. An deren Stelle sind »Fähigkeitenweichen« getreten. Diese fragen nicht allgemein den Namen des Browsers ab und versuchen Rückschlüsse auf die Unterstützung gewisser Techniken, sondern prüfen konkret die Existenz derjenigen JavaScript-Objekte, die im Laufe des Scriptes verwendet werden. Entscheidend ist dann, ob die nötigen Objekte existieren und korrekt funktionieren, etwa dass Eigenschaften einen erwarteten Wert oder Methoden das spezifizierte Ergebnis haben.
Unter anderem aus diesen Gründen spielt die Abfrage von Objekten heutzutage eine zentrale Rolle in JavaScript. Leider sieht eine Objektabfrage im Einzelfall sehr unterschiedlich aus. Welche Abfrage in welchem Fall die effektivste und zuverlässigste ist, erschließt sich nicht ohne Weiteres. Dieser Artikel soll die Grundlagen einer Objektabfrage erklären und anschließend die verschiedenen verbreiteten Objektabfragen diskutieren. Ziel ist es, die Funktionsweise und die geeigneten Anwendungen verschiedener Abfrage-Techniken zu vermitteln.
Bestandteile einer Objektabfrage
Objektabfragen haben drei Ebenen:
- Abfrage der Existenz: Existiert ein Objekt überhaupt? (Hat es überhaupt irgendeinen Wert oder ist es »nicht definiert«?)
- Abfrage des Types: Hat ein Objekt den gewünschten Typ?
- Wertabfragen: Abfrage des Wertes: Hat ein Objekt den gewünschten Wert?
Diese Abfragen müssen manchmal gestaffelt sein: Denn wenn ein Objekt gar nicht existiert, ist unter Umständen Vorsicht geboten bei der Abfrage des Types. Und die Abfrage des Wertes schließt ein, dass ein bestimmter Typ vorausgesetzt wird. Am Anfang steht daher die Überlegung, welche dieser Ebenen überhaupt geprüft werden soll.
Boolean-Abfragen
Unter Abfragen verstehen wir hier vor allem bedingte Verzweigungen mit if (...) { ... } else { ... }
. Im engeren Sinne werden wir uns mit der Bedingung beschäftigen, die bei der if-Anweisung zwischen den runden Klammern notiert wird. Dieselben Bedingungen finden aber auch bei anderen bedingten Anweisungen, nämlich dem sogenannten konditionalen Operator und bei switch-Fallunterscheidungen Verwendung.
Diese Bedingung ist ein beliebiger JavaScript-Ausdruck (»Expression«), welcher einen Boolean-Wert ergeben muss – das heißt true
oder false
. Der JavaScript-Interpreter wandelt das Ergebnis des Ausdrucks zwischen den Klammern automatisch in den Typ Boolean um, sofern es einen anderen Typ hat. Diese Umwandlung gehorcht festen Regeln, die wir nun kennenlernen werden.
Was ergibt also in Boolean umgewandelt true
? Anders herum gefragt: Welche Werte ergeben in Boolean umgewandelt false
?
- Der Boolean-Wert false ergibt logischerweise false.
- Die Werte null und undefined ergeben false.
- Die Zahlen (Typ Number) 0 und NaN ergeben false.
- Ein leerer String ("") ergibt false.
Alle anderen Werte ergeben true.
Das bedeutet: Vordefinierte Objekte wie window
und window.document
, Funktionsobjekte, DOM-Knoten-Objekte, darunter Elementobjekte, sowie Array-, Date- und RegExp-Objekte ergeben allesamt true
. Kurz gesagt ergeben nicht-leere Strings, Zahlen ungleich 0 bzw. NaN und »richtige« Objekte (Objects, dazu später mehr) true
.
Diese Regeln sind normativ im ECMAScript-Standard spezifiziert, speziell in der internen Funktion ToBoolean, welche u. a. bei der Verarbeitung eines if-Statements aufgerufen wird.
if (objekt)
Prüft, ob eine globale oder lokale Variable nach Boolean umgewandelt true
ergibt. Wenn weder eine lokale noch eine globale Variable dieses Namens existiert, bricht das Script hier mit einem Ausnahmefehler (einer exception) ab: ReferenceError: objekt not defined
.
Eignet sich zur Abfrage, ob einer deklarierten lokalen Variable ein Wert zugewiesen wurde, der bei der Umwandlung in Boolean true
ergibt. Deklariert bedeutet, dass var objekt; notiert wurde oder die Variable in der Parameterliste der Funktion aufgeführt ist, ohne dass ein Wert für sie übergeben wurde. objekt
hat dann den speziellen Wert undefined
, was in Boolean umgewandelt false
ergibt.
false
sowie null ebenfalls false
.
if (objekt == true)
Dies ist eine lange Schreibweise von if (objekt)
. Sie hat jedoch nicht denselben Effekt, sondern funktioniert intern ganz anders.
Wenn Sie den Vergleichsoperator verwenden, so wird der sogenannte Abstract Equality Comparison Algorithm (abstrakter Algorithmus zur Ermittlung der Gleichheit) angewendet. Dieser wandelt object
nicht einfach in Boolean um. Wie er genau abläuft, hängt von den Typen der beiden Operanden ab (hier objekt
und true
).
Wenn beide Typen sich unterscheiden, so wird zunächst der Boolean-Operand mithilfe von ToNumber in eine Zahl (Number) umgewandelt. true
ergibt dabei 1, false
ergibt 0. Der Vergleich objekt == true
wird also zu objekt == 1
umgeschrieben. Danach wird objekt
ebenfalls in eine Zahl umgewandelt, um die beiden Operanden vergleichen zu können. Falls objekt
ein »echtes« Objekt (Object) ist, so wird das Objekt in einen einfachen Wert (Primitive) umgewandelt, indem dessen Methoden valueOf
oder toString
aufgerufen werden. (Zur Unterscheidung zwischen Objects und Primitives siehe unten.)
Kurz gesagt, dabei kann etwas ganz anderes herauskommen als beim einfachen if (objekt). Ein paar Beispiele:
Eingabe | if (objekt) alert('ja'); else alert('nein'); |
if (objekt == true) alert('ja'); else alert('nein'); |
---|---|---|
0 |
nein | nein |
1 |
ja | ja |
123 |
ja | nein |
"" |
nein | nein |
" " |
ja | nein |
"ein String" |
ja | nein |
"0" |
ja | nein |
"1" |
ja | ja |
window |
ja | nein |
window.setTimeout |
ja | nein |
{ valueOf : function () { return 0; } } |
ja | nein |
{ toString : function () { return "ein Object"; } } |
ja | nein |
Ein ausdrücklicher Vergleich mit true
bzw. false
führt nur selten zu dem gewünschten Resultat, da intern mit Zahlen als Vergleichswerten gearbeitet wird. Sofern dieses Verhalten nicht ausdrücklich gewünscht ist, sollten Sie if (objekt)
und if (!objekt)
anstelle von if (objekt == true)
und if (objekt == false)
verwenden. Das gilt insbesondere für Fähigkeitenabfragen.
if (objekt == undefined)
Genauere Überprüfung, ob eine globale oder lokale Variable deklariert wurde, ihr aber kein Wert zugewiesen wurde. Wenn ein Funktionsparameter in der Parameterliste aufgeführt ist, aber kein Wert übergeben wurde, existiert eine entsprechende lokale Variable ohne Wert.
function funktionMitParameter (parameter) { if (parameter == undefined) { alert('Es wurde kein Parameter übergeben (oder ausdrücklich undefined)'); } } // Aufruf ohne Parameter funktionMitParameter();
Hat die Variable den Wert null
, so ergibt der Vergleich mit undefined
ebenfalls true
. Um diese Mehrdeutigkeit zu vermeiden, können Sie if (objekt === undefined)
notieren. Der Identitätsoperator ===
überprüft sowohl die Gleichheit des Typs (hier Undefined) als auch die Gleichheit des Wertes (hier undefined).
Wenn keine Variable dieses Namens existiert, bricht das Script an dieser Stelle mit einem Ausnahmefehler (einer exception) ab: ReferenceError: objekt not defined
.
if (objekt == wert)
Beispielsweise if (objekt == "string")
oder if (objekt == 1234)
usw. Überprüfung der Wertgleichheit von globalen oder lokalen Variablen.
Damit die Vergleiche die erwarteten Resultate bringen, sollten beide Operanden vom gleichen Typ sein. Andernfalls erfolgt eine automatische Umwandlung auf Basis des beschriebenen Gleichheits-Algorithmus, der beide Operanden in eine Zahl (Number) umzuwandeln versucht.
Wenn keine Variable dieses Namens existiert, bricht das Script an dieser Stelle mit einem Ausnahmefehler (einer Exception) ab: ReferenceError: objekt not defined
.
if (objekt.eigenschaft) und if (objekt["eigenschaft"])
Prüft, ob ein Objekt eine Eigenschaft (Unterobjekt) besitzt, die in Boolean umgewandelt true
ergibt.
Wenn das Objekt keine Eigenschaft dieses Namens besitzt, bricht das Script an dieser Stelle nicht mit einem Ausnahmefehler ab. Der Ausdruck objekt.eigenschaft
ergibt dann einfach undefined
, welches in Boolean umgewandelt false
ergibt. Dadurch würde der if-Anweisungsblock nicht ausgeführt. Sie können daher auch if (objekt.eigenschaft == wert)
verwenden, um auf einen bestimmten Wert zu prüfen, ohne dass das Script abbricht, wenn die Eigenschaft nicht existiert.
Dies ist die beste Methode für »Fähigkeiten-Weichen«, die abfragen, ob vordefinierte Objekte (bzw. Eigenschaften oder Methoden) im jeweiligen Browser zur Verfügung stehen. Besonders für die Existenzabfrage von Methoden eignet sich diese Schreibweise.
if (document.getElementById) { let elem = document.getElementById("a"); if (elem.scrollIntoView) { elem.scrollIntoView(); } }
Existieren die Methoden getElementById
bzw. scrollIntoView
, werden sie verwendet, anderweitig wird der entsprechende Code übersprungen.
Interessant ist ferner, dass sich auf diese Weise auch globale Variablen überprüfen lassen. Denn globale Variablen sind in JavaScript Eigenschaften des globale Objektes window
. Also kann man einfach if (window.globaleVariable)
oder if (window["globaleVariable"])
notieren. Der Vorteil gegenüber if (globaleVariable)
ist, dass das Script nicht mit einem Ausnahmefehler abbricht, wenn selbige Variable nicht existiert.
Typabfragen
if (typeof objekt == "typ") und if (typeof objekt.eigenschaft == "typ")
Mit dem typeof
-Operator lässt sich abfragen, ob eine Variable bzw. eine Objekteigenschaft einen bestimmten Typ hat. typeof
gibt einen String zurück, je nach Typ des Operanden gemäß der folgenden Tabelle:
Typ des Operanden | typeof-Rückgabe |
---|---|
Undefined | "undefined" |
Null | "object" |
Boolean | "boolean" |
Number | "number" |
String | "string" |
Funktionsobjekte | "function" |
sonstige Objekte (»Objects«, siehe unten) | "object" |
typeof
in JavaScript verhält sich ganz anders als entsprechende Operatoren bzw. Funktionen in anderen Programmiersprachen. Das hat damit zu tun, wie JavaScript intern organisiert ist. Zum Verständnis von typeof
ist ein kleiner Exkurs nötig:
Objects und Primitives
JavaScript (ECMAScript) behandelt zwar alles als Objekt, macht eine Unterscheidung zwischen sogenannten Primitives (einfachen Werten) und Objects (»richtigen«, vollwertigen Objekten). Diese Doppelung betrifft Boolean-, Number- und String-Werte, diese können als Primitive oder als Object notiert werden. Üblicherweise arbeitet man mit Primitives: let string = "Hallo Welt"
sowie die üblichen String-Operationen erzeugen String-Primitives, während let string = new String("Hallo Welt");
ein String-Object erzeugt. Dieser Unterschied macht sich vor allem an zwei Stellen bemerkbar:
- Primitives werden als Kopie an Funktionen übergeben, während Objects als Referenz (genauer gesagt als Referenzkopie) übergeben werden.
- Der Vergleichsoperator
==
ergibt beim Vergleich zweier Objects nur danntrue
, wenn es sich um ein und dasselbeObject
handelt. Das heißt, er verhält sich in dem Fall wie der Identitätsoperator===
. Daher ergibtnew String("Hallo Welt") == new String("Hallo Welt")
kurioserweisefalse
. Bei Primitives hingegen gibt es eine Gleichheit unabhängig von der Identität:"Hallo Welt" == "Hallo Welt"
ergibt selbstverständlichtrue
.
Was hat das nun mit typeof
zu tun? typeof
unterscheidet im Grunde nur zwischen undefinierten Werten (Undefined
), den drei Primitives (Boolean, Number, String) und Objects (Funktionen vs. alle anderen Objects). Was null, kein Primitive und kein Funktionsobjekt ist, klassifiziert typeof
zusammenfassend als "object". Dadurch gibt typeof
sehr häufig "object" zurück, was Verwirrung stiftet. Zum Beispiel werden Array-, Date- oder RegExp-Objekte als "object" klassifiziert – diese sind aus Sicht von typeof
kein eigenen Typen. Aber auch der Wert null
wird als "object" klassifiziert, obwohl es sich strenggenommen um ein Primitive handelt – dies kann einige Verwirrungen stiften.
Browserprobleme und Konsequenzen
Dummerweise setzen nicht alle Browser diese Vorgaben der obigen Tabelle konsequent um, sodass typeof
in verschiedenen Browsern z. B. bei gleichen vordefinierten Objekten unterschiedliche Resultate erzeugt. In manchen Browsern identifiziert typeof
ein vordefiniertes Funktionsobjekt fälschlicherweise als "object" anstatt als "function".
Diese Einschränkungen und Fallstricke führen dazu, dass eine Abfrage typeof
nur in bestimmten Fällen das Mittel der Wahl ist. Verwenden Sie typeof
möglichst nur bei einfachen Werten (Boolean-, Number- und String-Primitives) und nur bei selbst definierten Funktionen. Achten Sie auf mögliche Browserunterschiede und die Besonderheiten bei der Klassifizierung.
Anwendungsgebiete
Nichtsdestoweniger ist typeof
die zweitwichtigste Abfragetechnik in der browserübergreifenden Programmierung neben if (objekt.unterobjekt). Der Vorteil ist, dass nur der Typ überprüft wird, nicht der Wert selbst in Boolean umgewandelt und auf Gleichheit mit true getestet wird, wie es z. B. bei if (objekt.unterobjekt)
der Fall ist. Wenn bloß die Existenz einer Variable geprüft werden soll, es sich aber beispielsweise durchaus um einen leeren String, die Zahl 0 oder den Boolean-Wert false handeln darf, eignet sich typeof
.
Abfragen mit typeof
sind wie gesagt weniger streng als if (objekt.unterobjekt)
, da der Wert selbst keiner Boolean-Prüfung unterzogen wird. Dennoch sind die beiden Möglichkeiten in vielen Fällen austauschbar. Oft ist es eine Geschmackfrage, welche Methode verwendet wird. Meine Empfehlung ist, häufiger if (objekt.unterobjekt)
zu verwenden und typeof
speziell dann zu verwenden, wenn der Inhalt egal ist, solange der Typ stimmt.
Wenn keine Variable bzw. Eigenschaft den angegebenen Namens existiert, bricht das Script beim typeof
-Operator nicht mit einem Ausnahmefehler ab, sondern typeof
liefert den String "undefined" zurück.
Robuste Scripte durch passende Typabfragen und Typumwandlungen
Strenge Typabfragen können verwirrend sein, da JavaScript flexibel mit Typen umgeht, um die Programmierung zu vereinfachen. Je nach Kontext werden Werte bei der Code-Ausführung automatisch in andere Typen konvertiert, z. B. damit Operanden und Funktionen mit den erwarteten Typen arbeiten können. Dies ist vielmals erwünscht und findet breite Verwendung, ohne dass JavaScript-Programmierer sich dessen notwendigerweise bewusst sind. Es ist nicht immer problematisch, wenn eine Variable z. B. anstelle des Wertes 250 vom Typ Number den Wert "250" vom Typ String enthält. Es kann aber ein großes Problem werden. Etwa variable.toFixed()
funktioniert nur bei Number-Werten und der Operator + hat eine ganz andere Bedeutung, wenn ein Operand ein String ist.
Wenn Sie also typeof
benutzen, um einen speziellen Typ abzufragen, sollten Sie sich mit den Möglichkeiten der automatischen und manuellen Typen-Konvertierung vertraut machen. Benutzen Sie etwa parseInt oder parseFloat zur Umwandlung von Strings in Zahlen und toString zur expliziten Umwandlung von Zahlen in Strings. So können Sie robuste, tolerante Programme schreiben:
function zahlenverarbeitung (parameter) { let zahl; if (typeof parameter == "string") { // Es wurde ein String übergeben, wandle in Zahl um zahl = parseFloat(parameter); if (isNaN(zahl) { // Umwandlung in String ergab keinen brauchbaren Wert return false; } } else if (typeof parameter == "number") { // Es wurde eine Zahl übergeben, wir können direkt damit arbeiten zahl = parameter; } else { // Es wurde kein brauchbarer Wert übergeben return false; } // Arbeite mit zahl weiter }
Das obige Beispiel ist bewusst sehr ausführlich, um das Reagieren auf verschiedene Parameter-Typen zu demonstrieren. Konkret diese Logik ließe sich auch kompakter ohne typeof
umsetzen, indem der Parameter direkt parseFloat()
gegeben wird und anschließend nur noch geprüft wird, ob es sich um eine gültige Zahl handelt:
function zahlenverarbeitung (parameter) { let zahl = parseFloat(parameter); if (isNaN(zahl) { // Umwandlung in String ergab keinen brauchbaren Wert return false; } // Arbeite mit zahl weiter }
Wertabfragen
if (typeof objekt != "undefined") und if (typeof objekt.eigenschaft != "undefined")
Prüft, ob eine lokale oder globale Variable bzw. eine Objekteigenschaft dieses Namens existiert und zudem einen Wert besitzt (der nicht vom Typ Undefined ist).
Aufgrund der beschriebenen Eigenheiten und Browser-Probleme wird typeof
häufig in diesem negativen Sinne gebraucht. Anstatt abzufragen, ob ein Objekt einen bestimmten Typ hat, wird bloß abgefragt, ob es existiert und irgendeinen anderen Typ als Undefined besitzt. Damit kann beispielsweise die bloße Existenz vordefinierter Objekte in Erfahrung gebracht werden oder geprüft werden, ob ein Funktionsparameter gesetzt wurde, unabhängig davon, welchen Typ und welchen Wert dieser hat.
Der negative Vergleich mit "undefined
" ist zwar ungenauer als die Prüfung auf einen oder mehrere bestimmte Typen, erfüllt aber oft trotzdem den gewünschten Zweck. Diese Methode findet an ähnlichen Stellen Verwendung wie if (objekt.unterobjekt)
.
if (objekt == null) und if (objekt.unterobjekt == null)
Der Vergleich mit null
ergibt true
, wenn das Objekt den Wert null
oder undefined
ist (siehe auch den Abschnitt zu undefined).
Wenn keine Variable dieses Namens existiert, bricht das Script an dieser Stelle mit einem Ausnahmefehler (einer Exception) ab: ReferenceError: objekt not defined
.
Zur Objekterkennung eignet sich die Prüfung auf null
weniger. Sie können jedoch in ihren eigenen Programmen den Wert null verwenden, um »kein Wert« von Werten wie "", 0 und false abzugrenzen. Sie können z.B. eine eigene Funktion null zurückgeben lassen, um zu zeigen, dass die Funktion korrekt ausgeführt wurde, aber das Ergebnis »kein Wert« ist (auch kein leerer String oder 0). Ähnlich handhaben es einige Methoden des W3C-DOM. In diesen Fällen ist der Vergleich mit null angebracht.
if ("eigenschaft" in objekt)
Diese relativ unbekannte Abfrage prüft, ob das Objekt eine Eigenschaft mit dem angegebenen Namen besitzt. Weder Typ noch Wert werden dabei überprüft. Der Ausdruck ergibt direkt true
oder false
. Es entspricht if (typeof objekt.eigenschaft != "undefined")
bis auf den Fall, in dem die Eigenschaft zwar gesetzt ist, aber den Wert undefined
hat.
Der Eigenschaftsname kann hier direkt als String angegeben werden oder als String-Variable, die den Namen der zu prüfenden Eigenschaft enthält. In letzterem Fall notiert man if (stringVariable in objekt)
.
Ein Beispiel ist die Abfrage, ob der Browser einen gewissen Event-Typ unterstützt . Unterstützt der Browser beispielsweise den Event hashchange
, so existiert die Eigenschaft onhashchange
. Wenn kein Event-Handler registriert ist, ist diese Eigenschaft jedoch initial leer, üblicherweise null.
if ('onhashchange' in window) { // Event wird unterstützt, registriere einen Event-Handler window.onhashchange = function () { ... }; } else { // Event wird nicht unterstützt, Alternativtechniken greifen // Firefox braucht eine Extra-Abfrage }
Die Praxis ist etwas komplizierter, da diese Abfrage im Firefox ein falsches Resultat ergibt. Wie der verlinkte Artikel beschreibt, existiert jedoch eine Alternative für Firefox.
Der in-Operator ist vor allem aus for-in-Schleifen bekannt. Dort hat er allerdings eine ganz andere Bedeutung und führt dazu, dass der Variablen auf der linken Seite nacheinander die Eigenschaftsnamen zugewiesen werden und für Eigenschaft der Schleifenkörper ausgeführt wird.
Wenn keine Eigenschaft mit dem angegebenen Namen existiert, bricht das Script an der Stelle der Verwendung des in-Operators nicht mit einem Ausnahmefehler ab, sondern liefert einfach den Boolean-Wert false zurück.
try { /* direkt objekt benutzen */ } catch (e) {}
Das try-catch-Statement dient eigentlich dazu, Ausnahmefehler (exceptions) abzufangen und sie im catch
-Zweig selbst zu behandeln. Damit lässt sich punktuell auf einen aufgetretenen Fehler reagieren, der sonst zum Abbruch des Scriptes führen würde. Dieses Konzept ist eigentlich sehr brauchbar. Allerdings gibt es zwei Probleme, sowohl grundlegender als auch praktischer Art.
Zum ersten wird try-catch
in den wenigsten Fällen sinnvoll verwendet. Oft wird der catch-Zweig leer gelassen, bloß um eventuelle Exceptions und damit verbundene Fehlermeldungen im Browser zu unterdrücken. Eine Fehlerbehandlung findet also nicht statt. try-catch
wird in dieser Weise inflationär gebraucht, anstatt zielgenaue Objektabfragen bzw. tatsächliche Fehlerbehandlung einzusetzen.
Zum zweiten ist es mit try-catch
nicht möglich, spezifisch auf einen Fehler zu reagieren, wenn große Programmteile in try-Blöcke untergebracht werden. Das Fehlerobjekt, auf das man im catch-Block Zugriff hat, enthält wenig brauchbare Informationen. Die Fehlermeldung kann höchstens abgefangen werden, um sie beispielsweise mit XMLHttpRequest an den Server zurückzusenden. Dort könnten alle Fehlermeldungen gespeichert werden, um Scripte zu verbessern, damit sie in Zukunft keine Exceptions mehr produzieren.
Der Einsatz von try-catch
zur Fehlerunterdrückung während der Entwicklung führt dazu, dass Scriptfehler nicht rechtzeitig erkannt werden. Robuster, fehlertoleranter JavaScript-Code sollte im Produktiveinsatz auch in Sonderfällen keine unerwarteten Exceptions auslösen. Daher erwähnt dieser Artikel jeweils, welche Abfragetechniken Exceptions auslösen und welche nicht, auch wenn die angesprochene Variable bzw. Eigenschaft nicht existiert. Mit diesen »sicheren« Objektabfragen können Sie Exceptions von vornherein vermeiden.
Es gibt noch weitere Argumente gegen einen unbedachten Einsatz von try-catch
: Beispielsweise ist die Ausführung viel langsamer als die hier beschriebenen zielgenauen Abfragen. Zusammenfassend: Verwenden Sie try-catch
nur im Notfall, wenn andere Objektabfragen nicht möglich sind oder nicht greifen.
Es gibt nur wenige Fälle, in denen try-catch
nützlich oder gar nötig ist. Etwa wenn bekannt und spezifiziert ist, dass eine Anweisung bei der regulären Verwendung eine Exception auslösen kann. Doch nur wenige JavaScript- und DOM-Operationen erzeugen bei korrekter Anwendung und sinnvollen Eingabedaten Exceptions.
try-catch
soll keinesfalls verdammt werden. Sein Einsatz ist lediglich zum Zwecke der Fehlerunterdrückung und Fallunterscheidung nicht sinnvoll, weil genauere und bessere Alternativen für robuste Scripte existieren. Es spricht nichts dagegen, try-catch
bei einer erwarteten Exception zu verwenden, um im catch-Zweig Alternativen anzuwenden und die Aufgabe auf eine andere Weise zu lösen. Es spricht auch nichts gegen den kontrollierten Einsatz von try-catch
und throw
, um die bestimmte Ausnahme auf einer höheren Ebene zu behandeln.
Weblinks
- SELFHTML-Weblog: Der sinnvolle Einsatz von JavaScript
- SELFHTML-Forum: Überprüfen, ob eine Variable existiert
- SELFHTML-Forum: »object has no properties« verhindern
englischspachig: