Spezifischere Alternative für de Typeof Operator in Javascript

Wer viel mit JavaScript arbeitet wird schnell die Grenzen des typeof Operators kennen lernen. Für einfache Datentypen arbeitet er sehr gut und präzise. Allerdings sind wir auf 6 Typen beschränkt: function, object, string, number, boolean, undefined. Auf den ersten Blick wirkt das zwar ausreichend, doch wird anhand eines Beispiels schnell klar, wo die Grenzen des typeof Operators sind:

typeof (new Date)
// Ergebnis: "object"
typeof (/0-9/)
// Ergebnis: "object"
typeof ([0,2,4])
// Ergebnis: "object"

An diesem Beispiel sehen wir, dass wir nicht eindeutig bestimmen können, um welche Art von Objekt es sich handelt. So lässt sich nicht prüfen, ob es sich um ein Array handelt, durch welches wir iterieren können, oder ob es ein Datum-Objekt ist, bei welchem wir dies tunlichst lassen sollten.

Zum Glück gibt es jedoch eine Möglichkeit den genau Typ zu bestimmen. Laut definition beinhaltet jedes Object in JavaScript die sogenannte [[Class]]-Eigenschaft. Dies ist ein String der genau definiert, um was für einen Objekt-Typen es sich handelt. Klingt super! Doch wie kommen wir an diese Eigenschaft? Leider sieht JavaScript keine direkte Funktion für den Zugriff auf die Eigenschaft vor.
Allerdings gibt es einen Seiteneffekt, den man sich zunutze machen kann. Die toString-Methode eines Objectes gibt standardmäßig genau diese Eigenschaft zurück. Zumindest theoretisch…
Probieren wir dies doch mal aus:

[0,2,4].toString(); 
// Ergebnis: "0, 2, 4"

Das Ergebnis ist leider nicht wie erhofft der Typ des Objektes, sondern ein String mit den Werten des Arrays. Jeder der ein wenig mit JavaScript gearbeitet hat, wird sich hierüber auch nicht wundern. Doch warum ist das so. Wurde nicht eben gesagt, dass standardmäßig die .toString() Funktion den Typen des Objectes zurückliefert? Das tut sie auch, jedoch wird diese Funktion leider durch Objekteigene Methoden überschrieben, so dass wir uns eines Tricks bedienen müssen.

Dazu nutzen wir die Tatsache, dass das globale Object-Model auch eine prototypische Funktion “toString” hat. Diese kann generisch getypt werden. Das bedeutet, wir können diese Funktion mit dem Objekt aufrufen, von welchem wir den genauen Typ erfahren wollen. Am besten zeigt sich dies anhand eines Beispiels:

Object.prototype.toString.call(new Date);
// Ergebnis: "[object Date]"
Object.prototype.toString.call(/0-9/);
// Ergebnis: "[object RegExp]"
Object.prototype.toString.call([0,2,4]);
// Ergebnis:  "[object Array]"

Geschafft :) die Anfrage liefert den exakten Typ des Objektes. Jetzt können wir Arrays, Date-Objekte und sogar reguläre Ausdrücke auf ihren korrekten Typ prüfen. Da wir jedoch jedes mal einen String vergleich der Art: Object.prototype.toString.call([0,2,4]) === “[object Array]” machen müssten, können wir durch eine kleine Hilfsfunktion auch direkt den Typen aus dem String extrahieren.
An dieser Stelle ein Dankeschön an den Blog-Beitrag von Angus Croll von welchem diese Funktion stammt.

Wir bauen also eine einfache Funktion, die uns den entsprechenden Datentypen liefert:

function getType (obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}

Damit können wir jetzt vor dem Aufruf kritischer Funktionen prüfen, ob es sich bei dem Objekt auch um einen korrekten Datentypen handelt. Z.B.:

var arr = [0,1,2];
if (getType([arr]) === "array") { 
  alert("juhu ein Array mit der Länge " + arr.length);
}

An diesem Beispiel sieht man wieder einmal, JavaScript ist zu weit mehr in der Lage, als auf den ersten Blick sichtbar ist. Jedoch muss man erstmal die Funktionen und Möglichkeiten entdecken ;)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">