Typeof in JavaScript ist eigentlich sehr komplex, es kann für viele Dinge verwendet werden, weist aber auch viele seltsame Verhaltensweisen auf und zeigt auch bestehende Probleme und Lösungen auf.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FOperators%2Ftypeof
> Typ undefiniert
'undefiniert'
> typeof null // bekannter Fehler
'Objekt'
> Typ wahr
'boolean'
>Typ von 123
'Nummer'
> Art von „abc“
'Zeichenfolge'
> Funktionstyp() {}
'Funktion'
> Art von {}
'Objekt'
> Art von []
'Objekt'
> Typ der unbekannten Variablen
'undefiniert'
1. Prüfen Sie, ob eine Variable existiert und einen Wert hat.
typeof gibt in zwei Situationen „undefiniert“ zurück: wenn eine Variable nicht deklariert ist und wenn der Wert einer Variablen undefiniert ist. Beispiel:
> typeof undeclaredVariable === "undefiniert" true > var deklarierteVariable > typeof deklarierteVariable 'undefiniert' > typeof undefiniert 'undefiniert'
Es gibt andere Möglichkeiten, um festzustellen, ob ein Wert undefiniert ist:
> var value = undefiniert; > value === undefiniert wahr
Wenn diese Methode jedoch für eine nicht deklarierte Variable verwendet wird, wird eine Ausnahme ausgelöst, da nur typeof nicht deklarierte Variablen normal erkennen kann, ohne einen Fehler zu melden:
> undeclaredVariable === undefiniert ReferenceError: undeclaredVariable ist nicht definiert
Hinweis: Bei nicht initialisierten Variablen, formalen Parametern ohne übergebene Parameter und nicht vorhandenen Eigenschaften treten die oben genannten Probleme nicht auf, da auf sie immer zugegriffen werden kann und der Wert immer undefiniert ist:
> var deklarierteVariable; > deklarierteVariable === undefiniert wahr > (Funktion (x) { return x === undefiniert }()) wahr > ({}).foo === undefiniert wahr
Anmerkung des Übersetzers: Wenn Sie daher die Existenz einer globalen Variablen erkennen möchten, die möglicherweise nicht deklariert ist, können Sie auch if(window.maybeUndeclaredVariable){} verwenden.
Problem: typeof ist umständlich, eine solche Aufgabe zu erfüllen.
Lösung: Diese Art von Operation ist nicht sehr verbreitet, daher sind einige Leute der Meinung, dass es nicht nötig ist, eine bessere Lösung zu finden. Aber vielleicht schlägt jemand einen speziellen Operator vor:
> definierte undeclaredVariable false > var deklarierteVariable; > definierte deklarierteVariable false
Oder vielleicht braucht man auch einen Operator, der erkennt, ob eine Variable deklariert ist:
> deklarierte undeclaredVariable false > var deklarierteVariable; > deklarierte deklarierteVariable wahr
Anmerkung des Übersetzers: In Perl entspricht der oben definierte Operator definiert() und der oben deklarierte Operator entspricht exist().
2. Bestimmen Sie, ob ein Wert undefiniert oder null ist.
Problem: Wenn Sie überprüfen möchten, ob ein Wert definiert wurde (der Wert ist weder undefiniert noch null), dann stoßen Sie auf eine der bekanntesten Macken von typeof (die als Fehler angesehen wird): typeof null gibt „object“ zurück:
> typeof null 'Objekt'
Anmerkung des Übersetzers: Man kann nur sagen, dass es sich dabei um einen Fehler in der ursprünglichen JavaScript-Implementierung handelt, und so wurde der Standard nun in Version 8 standardisiert und vom Typ null === „null“ implementiert, aber er erwies sich letztendlich als undurchführbar. //wiki .ecmascript.org/doku.php?id=harmony:typeof_null
Lösung: Verwenden Sie für diese Aufgabe nicht „typeof“, sondern eine Funktion wie diese:
function isDefined(x) { return x !== null && x !== undefiniert }
Eine andere Möglichkeit besteht darin, einen „Standardwertoperator“ einzuführen, wobei der folgende Ausdruck defaultValue zurückgibt, wenn myValue nicht definiert ist:
myValue ?? defaultValue
Der obige Ausdruck entspricht:
(meinWert !== undefiniert && meinWert !== null) ?
Oder:
myValue ??= defaultValue
Tatsächlich handelt es sich um eine Vereinfachung der folgenden Aussage:
myValue = myValue ?? defaultValue
Wenn Sie auf eine verschachtelte Eigenschaft zugreifen, z. B. bar, benötigen Sie möglicherweise die Hilfe dieses Operators:
obj.foo.bar
Wenn obj oder obj.foo undefiniert ist, löst der obige Ausdruck eine Ausnahme aus.?? Ermöglicht dem obigen Ausdruck, den ersten gefundenen Wert zurückzugeben, wenn die Eigenschaften undefiniert oder null sind.
obj.??foo.??bar
Der obige Ausdruck entspricht:
(obj === undefiniert || obj === null) ? obj : (obj.foo === undefiniert || obj.foo === null) ?
3. Unterscheiden Sie zwischen Objektwerten und Grundwerten
Die folgende Funktion testet, ob x ein Objektwert ist:
function isObject(x) { return (typeof x === "function" || (typeof x === "object" && x !== null) }
Problem: Die obige Erkennung ist kompliziert, da typeof Funktionen und Objekte als unterschiedliche Typen betrachtet und typeof null „Objekt“ zurückgibt.
Lösung: Zur Erkennung von Objektwerten wird auch häufig die folgende Methode verwendet:
Funktion isObject2(x) { return x === Object(x);
Warnung: Sie denken vielleicht, dass Sie zum Erkennen hier das Objekt „instanceof“ verwenden können, aber „instanceof“ bestimmt die Instanzbeziehung mithilfe des Prototyps eines Objekts. Was ist also mit Objekten ohne Prototypen:
> var obj = Object.create(null); > Object.getPrototypeOf(obj) null
obj ist zwar ein Objekt, aber keine Instanz eines Werts:
> Typ von Objekt 'Objekt' > Objektinstanz von Objekt falsch
In der Praxis begegnet man einem solchen Objekt vielleicht selten, aber es existiert und hat seinen Nutzen.
Anmerkung des Übersetzers: Object.prototype ist ein Objekt, das standardmäßig existiert und keinen Prototyp hat.
>Object.getPrototypeOf(Object.prototype)null>typeof Object.prototype'object'>Object.prototype exampleof Object false
4.Was ist die Art des Grundwerts?
typeof ist die beste Möglichkeit, den Typ eines primitiven Werts zu überprüfen.
> typeof „abc“ ‚string‘ > typeof undefiniert ‚undefiniert‘
Problem: Sie müssen sich des seltsamen Verhaltens von typeof null bewusst sein.
> typeof null // Seien Sie vorsichtig, 'Objekt'!
Lösung: Die folgende Funktion kann dieses Problem beheben (nur für diesen Anwendungsfall).
function getPrimitiveTypeName(x) { var typeName = typeof x; switch(typeName) { case „undefiniert“: case „boolean“: case „number“: case „string“: return typeName; case „object“: if (x == = null) { return "null"; } default: // Keines der vorherigen Urteile wirft new TypeError("Der Parameter ist kein primitiver Wert: "+x);
Eine bessere Lösung: Implementieren Sie eine Funktion getTypeName(), die zusätzlich zur Rückgabe des Typs des Originalwerts auch das interne [[Class]]-Attribut des Objektwerts zurückgeben kann. So implementieren Sie diese Funktion (Anmerkung des Übersetzers: jQuery $.type ist eine solche Implementierung)
5. Ob ein bestimmter Wert eine Funktion ist
typeof kann verwendet werden, um zu erkennen, ob ein Wert eine Funktion ist > typeof function () {} 'function' > typeof Object.prototype.toString 'function'.
Im Prinzip Instanz von Die Funktion kann diese Anforderung auch erkennen. Auf den ersten Blick scheint die Schreibmethode jedoch eleganter zu sein: Jeder Frame und jedes Fenster verfügt über eigene globale Variablen Wenn das Objekt an ein anderes Framework übergeben wird, funktioniert die Instanz von nicht ordnungsgemäß, da die beiden Frameworks unterschiedliche Konstruktoren haben Aus diesem Grund gibt es in ECMAScript 5 eine Array.isArray()-Methode. Es wäre schön, wenn es eine Framework-übergreifende Methode gäbe, um zu überprüfen, ob ein Objekt eine Instanz eines bestimmten Konstruktors ist. Der obige getTypeName() ist eine verfügbare Problemumgehung , aber es könnte eine grundlegendere Lösung geben.
6.Übersicht
Die folgenden Funktionen sollten derzeit in JavaScript am dringendsten benötigt werden und können einige der funktionalen Funktionen ersetzen, die derzeit für typeof zuständig sind:
isDefined() (z. B. Object.isDefined()): kann als Funktion oder Operator verwendet werden
isObject()
getTypeName()
Ein rahmenübergreifender Mechanismus zum Erkennen, ob ein Objekt eine Instanz eines angegebenen Konstruktors ist
Um zu überprüfen, ob eine Variable deklariert wurde, ist möglicherweise kein eigener Operator erforderlich.