Rhino_02 - Erkennung von Datentypen
"Rhino_02" untersucht, wie man innerhalb eines JavaScript-Makros den Datentyp
eines (z.B. als Aufruf-Parameter an eine Funktion übergebenen) Objektes
ermitteln kann.
Zu diesem Zweck werden nacheinander Instanzen aller von JavaScript
unterstützten Datentypen (sowie einer "Benutzer-definierten" "Klasse")
an eine Funktion "checkTypeOf" übergeben, in welcher das jeweilige
Objekt genauer untersucht wird. Das Ergebnis dieser Untersuchung wird auf
"stdout" dokumentiert.
Der eigentliche Kern des Programmes steckt in der Funktion
"checkTypeOf":
|
/*******************************************************************************
* *
* checkTypeOf investigates the type characteristics of a given argument *
* *
*******************************************************************************/
function checkTypeOf (Name, Candidate) {
println(" - typeof(", Name, ") = ", typeof(Candidate));
try {
SuperClassesFound = 0; // global variable!
if (Candidate instanceof Object) reportInstanceOf(Name, "Object");
if (Candidate instanceof Boolean) reportInstanceOf(Name, "Boolean");
if (Candidate instanceof Number) reportInstanceOf(Name, "Number");
if (Candidate instanceof String) reportInstanceOf(Name, "String");
if (Candidate instanceof Array) reportInstanceOf(Name, "Array");
if (Candidate instanceof Function) reportInstanceOf(Name, "Function");
if (Candidate instanceof Date) reportInstanceOf(Name, "Date");
if (SuperClassesFound > 0) {
println(); // finish output line
} else {
println(" - ", Name, " has no (intrinsic) superclass");
};
} catch (Signal) {
/* nop */ // an exception is thrown during examination of "undefined"
};
PrototypesFound = 0; // global variable!
if (Object.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Object");
if (Boolean.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Boolean");
if (Number.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Number");
if (String.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "String");
if (Array.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Array");
if (Function.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Function");
if (Date.prototype.isPrototypeOf(Candidate)) reportPrototype(Name, "Date");
if (PrototypesFound > 0) {
println(); // finish output line
};
try {
if ("constructor" in Candidate) println(" - ", Name, " has a constructor");
} catch (Signal) {
/* nop */
};
try {
if ("prototype" in Candidate) println(" - ", Name, " has a prototype");
} catch (Signal) {
/* nop */
};
};
|
Als erstes wird geprüft, wie die Funktion "typeof()" auf das
Objekt reagiert. Anschließend wird mithilfe des
instanceof-Operators untersucht, ob sich das Test-Objekt von einem
der intrinsischen Datentypen ableitet. Auf ähnliche Weise wird
überprüft, ob das Objekt Datenfelder und Methoden aus einem der
intrinsischen Prototypen übernimmt. Zu guter Letzt wird mithilfe des
in-Operators explizit nach einem Konstruktor und einem Prototypen
für das Test-Objekt gesucht.
Schlechte Erfahrungen mit früheren Versionen des Programmes haben dazu
geführt, daß einige Passagen der Funktion als
try-catch-Block ausgeführt werden mußten - mit
mäßigem Erfolg (siehe dazu auch die nachstehende Programmausgabe).
"Rhino_02" wird ohne Kommandozeilen-Argumente aufgerufen
java Rhino Rhino_02.js
und liefert folgende Ausgabe:
|
Rhino_02 - investigates the detection of data types
testing type characteristics of a "Boolean" object
- typeof(Boolean) = boolean
- Boolean has no (intrinsic) superclass
testing type characteristics of a "Number" object
- typeof(Number) = number
- Number has no (intrinsic) superclass
testing type characteristics of a "String" object
- typeof(String) = string
- String has no (intrinsic) superclass
testing type characteristics of a plain object
- typeof(Object) = object
- Object is an instance of Object
- Prototype(s) of Object: Object
- Object has a constructor
testing type characteristics of an "Array" object
- typeof(Array) = object
- Array is an instance of Object, Array
- Prototype(s) of Array: Object, Array
- Array has a constructor
testing type characteristics of a "Date" object
- typeof(Date) = object
- Date is an instance of Object, Date
- Prototype(s) of Date: Object, Date
- Date has a constructor
testing type characteristics of a "Function" object
- typeof(Function) = function
- Function is an instance of Object, Function
- Prototype(s) of Function: Object, Function
- Function has a constructor
- Function has a prototype
testing type characteristics of an user-defined object
- typeof(UserObject) = object
- UserObject is an instance of Object, Function
- Prototype(s) of UserObject: Object, Function
- UserObject has a constructor
- UserObject has a prototype
testing type characteristics of a "null" object
- typeof(null) = object
- null has no (intrinsic) superclass
testing type characteristics of an undefined object
- typeof(undefined) = undefined
error while evaluating file "Rhino_02.js"
(reason: "Rhino$RhinoException: Rhino.evaluate: EvaluatorException while evaluating file "Rhino_02.js" (reason: "The undefined value has no properties.")")
|
Offensichtlich werden nur "primitive" Datentypen (boolean,
number, string) sowie Funktionsobjekte unmittelbar erkannt
- alle andere Datentypen sind aus Sicht von JavaScript nichts weiter als
"Objekte". Interessant ist übrigens auch die Klassifizierung explizit
"konstruierter" Objekte als Funktionsinstanzen (vermutlich, weil der verwendete
Konstruktor ein Funktionsobjekt ist).
Und obwohl eigentlich auch "primitive" Datentypen einen impliziten Prototypen
besitzen, wissen die Instanzen dieser Datentypen anscheinend nichts davon...
Bemerkenswert an der Ausgabe von Rhino_02 ist aber vor allem auch die Ausnahme,
die bei der Untersuchung eines nicht-definierten Objektes geworfen wird -
und die Tatsache, daß sich diese Ausnahme (zumindest unter Rhino) offenbar
nicht abfangen läßt! In der (Programmier-)Praxis bedeutet dies,
daß evtl. nicht-definierte Parameter einer Funktion möglichst
frühzeitig erkannt und z.B. durch passende Vorgabewerte ersetzt werden
müssen. Dies kann z.B. durch eine Konstruktion der Form
if (typeof(<argument>) == "undefined") ...;
geschehen.
Quelltexte
Das hier vorgestellte Skript ist im Quelltext verfügbar:
|
 |
| http://www.Andreas-Rozek.de/Rhino/Acquainting/Rhino_02.html |
(letzter Stand: 06.04.2002) |
|