Das instanceof
Schlüsselwort in JavaScript kann beim ersten Auftreten ziemlich verwirrend sein, da die Leute glauben, dass JavaScript keine objektorientierte Programmiersprache ist.
- Was ist es?
- Welche Probleme löst es?
- Wann ist es angebracht und wann nicht?
javascript
operators
instanceof
Alon Gubkin
quelle
quelle
"foo" instanceof String
=> falsch,1 instanceof Number
=> falsch,{} instanceof Object
=> falsch. Sag was?!"foo" instanceof String => false
ist richtig, weiltypeof "foo" == 'string'
.new String("foo") instanceof String => true
, weiltypeof String == 'function'
- Sie sollten die Funktion wie eine Klasse behandeln (Definition der Klasse). Variable wird zuinstanceof
einerfunction
(Klasse), wenn Sie sie als zuweisenvar v = new AnythingWhatTypeofEqualsFunction()
. Gleiches gilt für1
.typeof 1 == 'number'
- 'Nummer' ist nicht 'Funktion' :) Weiter -{} instanceof Object
istTRUE
in Knoten und modernen Browsern({}) instanceof Object
wird zurückkehrentrue
. Tatsächlich gibt Ihnen der von Ihnen geschriebene Code einen Fehler.Antworten:
Instanz von
Der LHS-Operand (Left Hand Side) ist das tatsächliche Objekt, das mit dem RHS-Operanden (Right Hand Side) getestet wird, der der eigentliche Konstruktor einer Klasse ist. Die grundlegende Definition lautet:
Hier sind einige gute Beispiele und hier ein Beispiel, das direkt von Mozillas Entwicklerseite stammt :
Eine erwähnenswerte Sache ist die
instanceof
Bewertung als wahr, wenn das Objekt vom Prototyp der Klasse erbt:Das ist
p instanceof Person
wahr, dap
erbt vonPerson.prototype
.Auf Anfrage des OP
Ich habe ein kleines Beispiel mit Beispielcode und einer Erklärung hinzugefügt.
Wenn Sie eine Variable deklarieren, geben Sie ihr einen bestimmten Typ.
Zum Beispiel:
Die oben zeigen Ihnen einige Variablen, nämlich
i
,f
undc
. Die Typen sindinteger
,float
und eine Benutzer - definierteCustomer
Datentypen. Typen wie die oben genannten können für jede Sprache verwendet werden, nicht nur für JavaScript. Wenn Sie jedoch mit JavaScript eine Variable deklarieren, definieren Sie keinen Typ explizit.var x
X kann eine Zahl / Zeichenfolge / ein benutzerdefinierter Datentyp sein. Also , wasinstanceof
tut , ist es das Objekt überprüft, ob es von der Art ist , angegeben , so von oben die EinnahmeCustomer
Objekt , das wir tun könnten:Oben haben wir gesehen, dass dies
c
mit dem Typ deklariert wurdeCustomer
. Wir haben es neu gemacht und geprüft, ob es vom Typ istCustomer
oder nicht. Sicher ist, es gibt wahr zurück. DannCustomer
prüfen wir immer noch mit dem Objekt, ob es ein istString
. Nein, definitiv nichtString
wir haben einCustomer
Objekt neu gemacht, keinString
Objekt. In diesem Fall wird false zurückgegeben.So einfach ist das wirklich!
quelle
color1 instanceof String;
dies true zurückgibt, weil color1 ein String ist.person p = new person()
p jetzt ein Personentyp und kein Zeichenfolgentyp.var zero = 0; alert(zero); zero = "0"; alert(zero)
wir sind ohne Probleme von einem Primitivint
zu einem Primitiv übergegangenstring
.int
in primitiv zu ändernstring
.Es gibt eine wichtige Facette, die in keinem der bisherigen Kommentare behandelt zu werden scheint: Vererbung. Eine Variable, die mithilfe von instanceof ausgewertet wird, kann aufgrund der prototypischen Vererbung für mehrere "Typen" true zurückgeben.
Definieren wir zum Beispiel einen Typ und einen Subtyp:
Nachdem wir nun ein paar "Klassen" haben, können wir einige Instanzen erstellen und herausfinden, wofür sie Instanzen sind:
Sehen Sie diese letzte Zeile? Alle "neuen" Aufrufe einer Funktion geben ein Objekt zurück, das von Object erbt. Dies gilt auch bei Verwendung der Kurzform zur Objekterstellung:
Und was ist mit den "Klassen" -Definitionen selbst? Wovon sind sie Beispiele?
Ich bin der Meinung, dass es wichtig ist zu verstehen, dass jedes Objekt eine Instanz von MEHRFACHEN Typen sein kann, da Sie (fälschlicherweise) davon ausgehen, dass Sie zwischen, sagen wir und Objekt und einer Funktion durch Verwendung von unterscheiden können
instanceof
. Da dieses letzte Beispiel zeigt eindeutig eine Funktion ist ein Objekt.Dies ist auch wichtig, wenn Sie Vererbungsmuster verwenden und die Nachkommen eines Objekts mit anderen Methoden als der Ententypisierung bestätigen möchten.
Hoffe, das hilft jedem beim Erkunden
instanceof
.quelle
SubFoo.prototype = new Foo();
weitere Methoden hinzufügen können, und diesubfoo instanceof Foo
Prüfung wird weiterhin bestandensubfoo instanceof SubFoo
Die anderen Antworten hier sind richtig, aber sie befassen sich nicht mit der
instanceof
tatsächlichen Funktionsweise, was für einige Sprachanwälte da draußen von Interesse sein kann.Jedes Objekt in JavaScript verfügt über einen Prototyp, auf den über die
__proto__
Eigenschaft zugegriffen werden kann. Funktionen haben auch eineprototype
Eigenschaft, die die Initiale__proto__
für alle von ihnen erstellten Objekte ist. Wenn eine Funktion erstellt wird, erhält sie ein eindeutiges Objekt fürprototype
. Derinstanceof
Bediener verwendet diese Eindeutigkeit, um Ihnen eine Antwort zu geben. Soinstanceof
könnte es aussehen, wenn Sie es als Funktion geschrieben haben.Dies ist im Wesentlichen eine Umschreibung von ECMA-262 Edition 5.1 (auch als ES5 bekannt), Abschnitt 15.3.5.3.
Beachten Sie, dass Sie jedes Objekt der
prototype
Eigenschaft einer Funktion neu zuweisen und die__proto__
Eigenschaft eines Objekts nach der Erstellung neu zuweisen können . Dies gibt Ihnen einige interessante Ergebnisse:quelle
__proto__
Eigenschaft " " im IE nicht zulässig ist. Wenn ich mich richtig erinnere, ist die direkte Manipulation des Eigentums auch nicht in der ECMA-Spezifikation enthalten, daher ist es wahrscheinlich eine schlechte Idee, es für andere Aufgaben als für akademische Zwecke zu verwenden.Object.getPrototypeOf(o)
. Dies__proto__
entspricht dem von Ihnen beschriebenen, entspricht jedoch ECMAScript.Ich denke, es ist erwähnenswert, dass instanceof durch die Verwendung des Schlüsselworts "new" beim Deklarieren des Objekts definiert wird. Im Beispiel von JonH;
Was er nicht erwähnte, ist dies;
Wenn Sie "new" angeben, wird der Endstatus der String-Konstruktorfunktion tatsächlich in die Variable color1 kopiert, anstatt nur den Rückgabewert festzulegen. Ich denke, dies zeigt besser, was das neue Schlüsselwort bewirkt.
Wenn Sie "new" verwenden, wird der deklarierten Variable der Wert "this" innerhalb der Funktion zugewiesen, während bei Nichtverwendung stattdessen der Rückgabewert zugewiesen wird.
quelle
new
mit einem der JavaScript-Typen zu arbeiten, was die akzeptierte Antwort für Anfänger viel verwirrender macht.text = String('test')
undoptions = {}
werden nicht voninstanceof
sondern getestet , sondern mittypeof
.Und Sie können es wie folgt zur Fehlerbehandlung und zum Debuggen verwenden:
quelle
quelle
Javascript ist eine prototypische Sprache, dh es werden Prototypen für die Vererbung verwendet. Der
instanceof
Operator testet, ob derprototype
Eigenschaftstyp einer Konstruktorfunktion in der__proto__
Kette eines Objekts vorhanden ist. Dies bedeutet, dass Folgendes ausgeführt wird (vorausgesetzt, testObj ist ein Funktionsobjekt):obj.__proto__ === testObj.prototype
>> Wenn dies der Fall ist,true
instanceof
wird zurückgegebentrue
.obj.__proto__.__proto__ === testObj.prototype
>> Wenn dies der Fall ist,true
instanceof
wird zurückgegebentrue
.testObj.prototype
danninstanceof
wird Operator zurückkehrenfalse
.Beispiel:
Es löste das Problem der bequemen Überprüfung, ob ein Objekt von einem bestimmten Prototyp stammt. Zum Beispiel, wenn eine Funktion ein Objekt empfängt, das verschiedene Prototypen haben kann. Bevor wir Methoden aus der Prototypenkette verwenden, können wir mit dem
instanceof
Operator überprüfen, ob sich diese Methoden auf dem Objekt befinden.Beispiel:
Hier wird in der
talk()
Funktion zunächst geprüft, ob sich der Prototyp auf dem Objekt befindet. Danach wird die entsprechende Methode zur Ausführung ausgewählt. Wenn Sie diese Prüfung nicht durchführen, kann dies dazu führen, dass eine nicht vorhandene Methode ausgeführt wird und somit ein Referenzfehler auftritt.Wir haben das schon durchgesehen. Verwenden Sie es, wenn Sie den Prototyp eines Objekts überprüfen müssen, bevor Sie etwas damit tun.
quelle
PersonX.prototype.talk
, damit dietalk
Funktion einfach ausgeführt werden kannperson.talk()
.__proto__
in der Dokumentation verwenden, es ist veraltet - schreiben SieObject.getPrototype()
stattdessenAuf die Frage "Wann ist es angebracht und wann nicht?", Meine 2 Cent:
instanceof
ist im Produktionscode selten nützlich, aber in Tests, in denen Sie behaupten möchten, dass Ihr Code Objekte des richtigen Typs zurückgibt / erstellt. Indem Sie explizit angeben, welche Arten von Objekten Ihr Code zurückgibt / erstellt, werden Ihre Tests leistungsfähiger als Werkzeug zum Verstehen und Dokumentieren Ihres Codes.quelle
instanceof
ist nur syntaktischer Zucker fürisPrototypeOf
:instanceof
hängt nur vom Prototyp eines Konstruktors eines Objekts ab.Ein Konstruktor ist nur eine normale Funktion. Genau genommen ist es ein Funktionsobjekt, da alles ein Objekt in Javascript ist. Und dieses Funktionsobjekt hat einen Prototyp, weil jede Funktion einen Prototyp hat.
Ein Prototyp ist nur ein normales Objekt, das sich innerhalb der Prototypenkette eines anderen Objekts befindet. Das bedeutet, in der Prototypenkette eines anderen Objekts zu sein, macht ein Objekt zu einem Prototyp:
Der
instanceof
Operator sollte vermieden werden, da er Klassen fälscht, die in Javascript nicht vorhanden sind. Trotz desclass
Schlüsselworts auch nicht in ES2015, daclass
es wieder nur syntaktischer Zucker für ... ist, aber das ist eine andere Geschichte.quelle
instanceof
abgeleitet vonisPrototypeOf
. Ich nenne das syntaktischen Zucker. Und Ihre MDN-Quelle ist ein Witz, nicht wahr?instanceof
mache aber nicht das Gleiche wieisPrototypeOf
. Das ist es.Ich habe gerade eine reale Anwendung gefunden und werde sie jetzt öfter verwenden, denke ich.
Wenn Sie jQuery-Ereignisse verwenden, möchten Sie manchmal eine allgemeinere Funktion schreiben, die auch direkt (ohne Ereignis) aufgerufen werden kann. Mit können Sie
instanceof
überprüfen, ob der erste Parameter Ihrer Funktion eine Instanz von ist,jQuery.Event
und entsprechend reagieren.In meinem Fall musste die Funktion entweder für alle (über ein Klickereignis auf einer Schaltfläche) oder nur für ein bestimmtes Element etwas berechnen. Der Code, den ich verwendet habe:
quelle