Javascript typeof – Typunterscheidung, sicherer Existenzcheck, Feature Detection
Number, String oder Boolean? typeof fragt den Typ eines Operanden ab. Der Operand kann ein Literal oder eine Variable, Funktion oder Objekt sein. Die Hauptanwendung war die Erkennung primitiver Datentypen, aber wirkungslos für komplexe Typen. Der Clou von typeof: Es ist die einzige sichere Existenzprüfung.
Wenn sich der Datentyp ändern kann: typeof
In Javascript wird der Typ einer Variablen nicht ausdrücklich vereinbart, sondern der Datentyp wird dynamisch im Laufe des Programms zugewiesen. typeof stellt fest, ob ein Operator vom Typ number oder string, object oder boolean ist.
const x = 5;
const num = "4.5";
const conso = document.querySelector(".conso");
if (typeof x === "number") {
conso.textContent = "number";
}
conso.textContent += ` ${typeof num}`;
typeof ist keine Methode, sondern ein Operator (wie z.B. ein "+"). Das Ergebnis von typeof ist ein String.
| typeof Undefined | "undefined" |
| typeof Null | "object" |
| typeof Boolean | "boolean" |
| typeof Number | "number" |
| typeof String | "string" |
| typeof Object | "object" |
| typeof Array | "object" |
Der typeof-Operator
typeof gibt einen String zurück, der den Typ des Operanden identifiziert. Der (nicht entwickelte) Operand kann ein String, eine Variable, ein Schlüsselwort oder ein Objekt sein. typeof kann z.B. prüfen, ob eine Variable definiert wurde: Wenn kein Wert mit einer Variablen verbunden werden kann, liefert der typeof-Operator immer undefined.
typeof kann auf zweierlei Weise aufgerufen werden:
1. typeof operand 2. typeof (operand)
Die Klammern sind optional.
let fn = new Function("…")
let height = 100 + 50;
let size = height + "px";
let today = new Date();
Der typeof-Operator gibt bei diesen Beispielen die folgenden Ergebnisse zurück:
typeof fn function typeof height number typeof size string typeof today object typeof foo undefined
Ein Blick in die Browserconsole:
[Log] typeof 123 = number
[Log] typeof 'abs' = string
[Log] typeof document.lastModified = string
[Log] typeof true = boolean
[Log] typeof {a:1} = object
[Log] typeof (function foo() {}) = function
[Log] typeof Date = function
[Log] typeof Math = function
[Log] typeof undefined = undefined
[Log] typeof (Symbol('foo')) = symbol
[Log] typeof null = object
[Log] typeof [1,2,3] = object
[Log] typeof NaN = number
Das Fiasko beginnt, wenn der typeof-Operand null ist: typeof(null) antwortet mit object. Das ist einfach falsch, oder? Nun, ECMAScript definiert null als primitiven Wert, der die absichtliche Abwesenheit des Werts eines Objekts wiederspiegelt (ECMA-262, 4.3.12 The typeof Operator null value ). Muss man einfach schlucken.
Ein lichter Moment von type of: Wird eine nicht definierte Variable mit typeof abgefragt, liefert typeof "undefined".
Was bedeutet "Javascript ist locker typisiert"?
Javascript verlangt keine Typangabe, sondern findet selber heraus, welcher Datentyp in x und y gespeichert wird. Wir dürfen einer Variablen zunächst einen String zuweisen und später einen numerischen Wert. Bei der Ausführung des Programms wird der Javascript-Interpreter die Daten in den korrekten Typ konvertieren. In jeder der folgenden Anweisungen wird Javascript den Typ der Variablen konvertieren:
| Anweisung | Konvertierung | Type |
|---|---|---|
| let item = 5.5; | Zuweisung eines Fließkommawerts | |
| item = 44; | Konvertierung in einen Integer | |
| item = "Heute scheint die Sonne"; | Konvertierung in einen String | |
| item = true; | Konvertierung in einen Boolean | |
| item = null; | Konvertierung in einen null-Wert |
Für die Operationen auf Variablen muss das Programm etwas über den Typ der Variablen wissen, sonst könnte das Programm diese Anweisung nicht auflösen:
let x = 100 + "Apple";
Was dabei herauskommt? Javascript würde »100Apple« mit type of als Typ string interpretieren:
let x = "100" + "px";
Das ist zunächst einmal schön bequem. Aber was passiert hier:
let x = 100 + 50 + "px";
Javascript liest die Anweisung von links nach rechts. Das Ergebnis ist der String "150px".
Number.isInteger, Number.isNaN
In Bezug auf Zahlen ist typeof nicht immer hilfreich: Sowohl Float (Fließkommazahlen) als auch Integer (Ganze Zahlen) sind vom Typ number. Erst ES6 hat die Abfrage mitgebracht, ob eine Variable einen Integer enthält.
const zweiundvierzig = 42; const einhalb = 0.5; console.log(Number.isInteger(zweiundvierzig)); // true console.log(Number.isInteger(einhalb)); // false console.log(Number.isInteger([17,42,49])); // false console.log(Number.isInteger(12.0)); // true
Number.isNaN() ist eine weitere Erleichterung im Kampf der Typabfragen.
console.log (Number.isNaN(17.5)); // false console.log (Number.isNaN(0/0)); // true console.log (Number.isNaN(undefined)); // false
Eine Abfrage, ob eine Variable eine Fließkommazahl oder Gleitkomma enthält, muss man selber erstellen.
function isFloat(n) {
return typeof n === "number" && !Number.isInteger(n);
}
Oder noch etwas weitreichender (schließt NaN und Infinity aus):
function isFloat(n) {
return Number.isFinite(n) && !Number.isInteger(n);
}
Ist die Variable ein Array? array.isArray
Fragen wir nach einem Array mit typeof [a,b,c], kommt object zurück und fragen wir nach einem Objekt typeof (myobj), ist die Antwort ebenfalls object. Arrays sind nicht anderes als Objekte mit besonderer Ausstattung, aber kein eigenständiger Datentyp.
Um herauszufinden, ob ein Objekt ein Array ist, hat EcmaScript 5 eine Sonderlösung ausgeworfen: Array.isArray(obj). isArray ist eine sogen. statische Array-Methode und gibt true zurück, wenn das Objekt ein Array ist und ansonsten false.
const months = ["Januar", "Februar", "März", "April"];
console.log(`*** ein Array? ${Array.isArray(months)}`);
Der Clou von typeof: Es ist die einzige sichere Existenzprüfung.
if (x === undefined) { } wirft einen ReferenceError, wenn x nie definiert wurde. Hingegen prüft typeof x ob eine Variable tatsächlich existiert – und zwar ohne Crash, auch wenn x total fehlt. Das liegt daran, dass typeof ein Operator und kein normaler Funktionsaufruf ist.
if (typeof x === "undefined") {
// x existiert nicht
}
typeof ist die einzige sichere Existenzprüfung, weil es keinen ReferenceError wirft und auch mit nicht deklarierten Variablen funktioniert.
Object.prototype.toString.call()
Das ist der ultimative Typ-Detektor in Vanilla-JS, funktioniert für alle eingebauten Objekte.
Object.prototype.toString.call(123); // "[object Number]"
Object.prototype.toString.call("abc"); // "[object String]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(new Date()); // "[object Date]"
Object.prototype.toString.call(new Map()); // "[object Map]"
Object.prototype.toString.call(/regex/); // "[object RegExp]"
| Situation | Methode | Beispiel |
|---|---|---|
| Primitive Werte | typeof | typeof 123 === "number" |
| Arrays | Array.isArray() | Array.isArray(x) |
| Beliebige JS-Objekte | Object.prototype.toString.call() | "[object Map]" → "Map" |
| Klasseninstanzen | instanceof | x instanceof Date |
| Robust in jeder Umgebung | Object.prototype.toString.call() | ✅ Beste Wahl allgemein |
Typecheck mit toString
toString wandelt Javascript-Objekte in Strings [object Object] um und kann als Erweiterung von typeof für eingebaute Objekte wie Array, Date, RegExp, Error … und als Alternative zu instanceof eingesetzt werden.
const el = document.querySelector(".tostring");
const today = new Date();
const arr = ["Elefant", "Hase", "Igel"];
const objToString = Object.prototype.toString;
el.insertAdjacentHTML("beforeend", `
today ${today}
today.toString() ${today.toString()}
${objToString.call(arr)}
${objToString.call(today)}
`);
typeof oder instanceof
typeof ist die Abfrage für primitive Datentypen, instanceof checkt, ob ein Objekt zu einem bestimmten Objekt oder einer Klasse gehört oder von einem übergeordneten Objekt / Klasse geerbt hat.
| agiert auf | gibt zurück | |
| typeof | primitiven Datentypen | string |
| instanceof | Objekten | true / false |
var today = new Date();
if (today instanceof Date) {
console.log ("Der Typ von today ist Date");
}