Czym jest operator instanceof w JavaScript?
Słowo kluczowe instanceof
w JavaScript może być dość mylące, gdy jest napotkane po raz pierwszy, ponieważ ludzie mają tendencję do myślenia, że JavaScript nie jest obiektowym językiem programowania.
- Co to jest?
- Jakie problemy rozwiązuje? Kiedy jest to właściwe, a kiedy nie?
10 answers
Instanceof
Operand lewej strony (LHS) jest rzeczywistym obiektem testowanym do operandu prawej strony (RHS), który jest faktycznym konstruktorem klasy. Podstawowa definicja brzmi:
Checks the current object and returns true if the object
is of the specified object type.
Oto kilka dobrych przykładów i oto przykład zaczerpnięty bezpośrednio z witryny programistycznej Mozilli:
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral"; //no type specified
color2 instanceof String; // returns false (color2 is not a String object)
Warto wspomnieć, że instanceof
ewaluuje na true, jeśli obiekt dziedziczy z prototypu classe:
var p = new Person("Jon");
p instanceof Person
Że is {[6] } is true since p
inherits from Person.prototype
.
Na żądanie OP
Dodałem mały przykład z przykładowym kodem i wyjaśnieniem.
Kiedy deklarujesz zmienną, nadajesz jej określony typ.
Na przykład:
int i;
float f;
Customer c;
Powyższe pokazuje kilka zmiennych, a mianowicie i
, f
, i c
. Do rodzaju należą następujące gatunki integer
, float
oraz zdefiniowany przez Użytkownika typ danych Customer
. Typy takie jak powyższe mogą dotyczyć dowolnego języka, a nie tylko JavaScript. Jednak w JavaScript, gdy deklarujesz zmienną, nie definiujesz jawnie typu var x
, x może być typem danych zdefiniowanym przez użytkownika. To, co instanceof
robi, to sprawdza obiekt, aby sprawdzić, czy jest on typu określonego tak od góry biorąc Customer
obiekt możemy zrobić:
var c = new Customer();
c instanceof Customer; //Returns true as c is just a customer
c instanceof String; //Returns false as c is not a string, it's a customer silly!
Powyżej widzieliśmy, że c
został zadeklarowany z typem Customer
. Zmieniliśmy go i sprawdziliśmy, czy jest typu Customer
, czy nie. Oczywiście, że tak. Następnie używając obiektu Customer
możemy sprawdź, czy jest to String
. Nie, na pewno nie String
dodaliśmy Customer
obiekt, a nie String
obiekt. W tym przypadku zwraca false.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-22 10:58:51
Jest ważny aspekt instanceof, który nie wydaje się być omówiony w żadnym z komentarzy do tej pory: dziedziczenie. Zmienna oceniana za pomocą instanceof może zwrócić true dla wielu "typów" ze względu na dziedziczenie prototypowe.
Na przykład zdefiniujmy typ i podtyp:
function Foo(){ //a Foo constructor
//assign some props
return this;
}
function SubFoo(){ //a SubFoo constructor
Foo.call( this ); //inherit static props
//assign some new props
return this;
}
SubFoo.prototype = new Foo(); // Inherit prototype
Teraz, gdy mamy kilka "klas", zróbmy kilka instancji i dowiedzmy się, czego są instancjami:
var
foo = new Foo()
, subfoo = new SubFoo()
;
alert(
"Q: Is foo an instance of Foo? "
+ "A: " + ( foo instanceof Foo )
); // -> true
alert(
"Q: Is foo an instance of SubFoo? "
+ "A: " + ( foo instanceof SubFoo )
); // -> false
alert(
"Q: Is subfoo an instance of Foo? "
+ "A: " + ( subfoo instanceof Foo )
); // -> true
alert(
"Q: Is subfoo an instance of SubFoo? "
+ "A: " + ( subfoo instanceof SubFoo )
); // -> true
alert(
"Q: Is subfoo an instance of Object? "
+ "A: " + ( subfoo instanceof Object )
); // -> true
Widzisz ostatnią linijkę? Wszystkie" nowe " wywołania funkcji zwraca obiekt, który dziedziczy po obiekcie. Jest to prawdą nawet przy użyciu skrótu tworzenia obiektów:
alert(
"Q: Is {} an instance of Object? "
+ "A: " + ( {} instanceof Object )
); // -> true
A co z samymi definicjami "klasy"? Jakie są ich przykłady?
alert(
"Q: Is Foo an instance of Object? "
+ "A:" + ( Foo instanceof Object)
); // -> true
alert(
"Q: Is Foo an instance of Function? "
+ "A:" + ( Foo instanceof Function)
); // -> true
Uważam, że zrozumienie, że każdy obiekt może być instancją wielu typów jest ważne, ponieważ ty mój (niepoprawnie) zakładasz, że możesz odróżnić, powiedzmy i obiekt i funkcję za pomocą instanceof
. Jak ten ostatni przykład wyraźnie pokazuje funkcja jest an obiekt.
Jest to również ważne, jeśli używasz dowolnych wzorców dziedziczenia i chcesz potwierdzić potomstwo obiektu za pomocą metod innych niż pisanie kaczką.
Mam nadzieję, że to pomoże każdemu odkrywać instanceof
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-30 16:09:26
Inne odpowiedzi tutaj są poprawne, ale nie wnikają w to, jak naprawdę działa, co może być interesujące dla niektórych prawników językowych.
Każdy obiekt w JavaScript posiada prototyp, dostępny za pośrednictwem właściwości __proto__
. Funkcje mają również właściwość prototype
, która jest początkową __proto__
dla dowolnych obiektów przez nie utworzonych. Gdy funkcja jest tworzona, otrzymuje unikalny obiekt dla prototype
. Operator instanceof
używa tej wyjątkowości, aby udzielić odpowiedzi. Oto co instanceof
może wyglądać, gdybyś napisał to jako funkcję.
function instance_of(V, F) {
var O = F.prototype;
V = V.__proto__;
while (true) {
if (V === null)
return false;
if (O === V)
return true;
V = V.__proto__;
}
}
Jest to w zasadzie parafrazowanie ECMA-262 edition 5.1 (znany również jako ES5), sekcja 15.3.5.3.
Zauważ, że możesz przypisać dowolny obiekt do właściwości prototype
funkcji i możesz przypisać obiekt __proto__
po jej zbudowaniu. To da ci kilka ciekawych wyników:
function F() { }
function G() { }
var p = {};
F.prototype = p;
G.prototype = p;
var f = new F();
var g = new G();
f instanceof F; // returns true
f instanceof G; // returns true
g instanceof F; // returns true
g instanceof G; // returns true
F.prototype = {};
f instanceof F; // returns false
g.__proto__ = {};
g instanceof G; // returns false
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-09 23:04:33
Myślę, że warto zauważyć, że instanceof jest definiowany przez użycie słowa kluczowego" new " podczas deklarowania obiektu. W przykładzie z JonH;
var color1 = new String("green");
color1 instanceof String; // returns true
var color2 = "coral";
color2 instanceof String; // returns false (color2 is not a String object)
Nie wspomniał o tym;
var color1 = String("green");
color1 instanceof String; // returns false
Podanie "new" faktycznie skopiowało stan końcowy konstruktora Łańcuchowego funkcji do var color1, a nie tylko ustawiło go na wartość zwracaną. Myślę, że to lepiej pokazuje, co robi nowe słowo kluczowe;
function Test(name){
this.test = function(){
return 'This will only work through the "new" keyword.';
}
return name;
}
var test = new Test('test');
test.test(); // returns 'This will only work through the "new" keyword.'
test // returns the instance object of the Test() function.
var test = Test('test');
test.test(); // throws TypeError: Object #<Test> has no method 'test'
test // returns 'test'
Użycie "new" przypisuje wartość" this " wewnątrz funkcji do zadeklarowana zmienna, podczas gdy jej nie używa, przypisuje wartość zwracaną.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-10 21:54:28
I możesz go użyć do obsługi błędów i debugowania, jak to:
try{
somefunction();
}
catch(error){
if (error instanceof TypeError) {
// Handle type Error
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle all other error types
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-22 11:00:28
//Vehicle is a function. But by naming conventions
//(first letter is uppercase), it is also an object
//constructor function ("class").
function Vehicle(numWheels) {
this.numWheels = numWheels;
}
//We can create new instances and check their types.
myRoadster = new Vehicle(4);
alert(myRoadster instanceof Vehicle);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-15 18:08:35
Na pytanie " Kiedy jest to właściwe, a kiedy nie?", moje 2 grosze:
instanceof
jest rzadko użyteczny w kodzie produkcyjnym, ale przydatny w testach, w których chcesz upewnić się, że Twój KOD Zwraca / tworzy obiekty właściwego typu. Mówiąc wprost o rodzajach obiektów zwracanych / tworzonych przez Twój kod, twoje testy stają się potężniejsze jako narzędzie do zrozumienia i dokumentowania kodu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-24 02:01:49
instanceof
jest tylko cukrem składniowym dla isPrototypeOf
:
function Ctor() {}
var o = new Ctor();
o instanceof Ctor; // true
Ctor.prototype.isPrototypeOf(o); // true
o instanceof Ctor === Ctor.prototype.isPrototypeOf(o); // equivalent
instanceof
zależy tylko od prototypu konstruktora obiektu.
Konstruktor jest zwykłą funkcją. Ściśle mówiąc jest to obiekt funkcyjny, ponieważ wszystko jest obiektem w Javascript. A ten obiekt funkcji ma prototyp, ponieważ każda funkcja ma prototyp.
Prototyp jest zwykłym obiektem, który znajduje się w łańcuchu prototypów innego obiektu. Czyli bycie w prototype chain of another object makes a object to a prototype:
function f() {} // ordinary function
var o = {}, // ordinary object
p;
f.prototype = o; // oops, o is a prototype now
p = new f(); // oops, f is a constructor now
o.isPrototypeOf(p); // true
p instanceof f; // true
Operator instanceof
powinien być unikany, ponieważ fałszuje klasy, które nie istnieją w Javascript. Pomimo słowa kluczowego class
nie w ES2015, ponieważ {[6] } jest znowu tylko składniowy cukier dla...ale to już inna historia.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-26 21:16:57
Co to jest?
Javascript jest językiem prototypowym, co oznacza, że używa prototypów do "dziedziczenia". operator instanceof
sprawdza, czy typ właściwości konstruktora prototype
jest obecny w łańcuchu __proto__
obiektu. Oznacza to, że zrobi to co następuje (zakładając, że testObj jest obiektem funkcji):
obj instanceof testObj;
- sprawdź, czy prototyp obiektu jest równy prototypowi konstruktora:
obj.__proto__ === testObj.prototype
> > jeśli jest totrue
instanceof
powrócitrue
.
/ Align = "left" / Na przykład: - powtórzy Krok 2, dopóki nie zostanie sprawdzony pełny prototyp obiektu. Jeśli nigdzie w łańcuchu prototypów obiektu nie jest dopasowane do
testObj.prototype
, toinstanceof
operator zwrócifalse
.
obj.__proto__.__proto__ === testObj.prototype
> > jeśli jest to true
instanceof
powróci true
.
Przykład:
function Person(name) {
this.name = name;
}
var me = new Person('Willem');
console.log(me instanceof Person); // true
// because: me.__proto__ === Person.prototype // evaluates true
console.log(me instanceof Object); // true
// because: me.__proto__.__proto__ === Object.prototype // evaluates true
console.log(me instanceof Array); // false
// because: Array is nowhere on the prototype chain
Jakie problemy rozwiązuje?
Rozwiązał problem wygodnego sprawdzania, czy obiekt wywodzi się z pewnego prototypu. Na przykład, gdy funkcja otrzymuje obiekt, który może mieć różne prototypy. Następnie, przed użyciem metod z łańcucha prototypów, możemy użyć operatora instanceof
, aby sprawdzić, czy te metody znajdują się na obiekcie.
Przykład:
function Person1 (name) {
this.name = name;
}
function Person2 (name) {
this.name = name;
}
Person1.prototype.talkP1 = function () {
console.log('Person 1 talking');
}
Person2.prototype.talkP2 = function () {
console.log('Person 2 talking');
}
function talk (person) {
if (person instanceof Person1) {
person.talkP1();
}
if (person instanceof Person2) {
person.talkP2();
}
}
const pers1 = new Person1 ('p1');
const pers2 = new Person2 ('p2');
talk(pers1);
talk(pers2);
Tutaj w talk()
funkcja najpierw jest sprawdzana, czy prototyp znajduje się na obiekcie. Następnie wybiera się odpowiednią metodę do wykonania. Nie wykonanie tego czeku może powoduje wykonanie metody, która nie istnieje, a tym samym błąd odniesienia.
Kiedy jest to właściwe, a kiedy nie?Już to przerabialiśmy. Użyj go, gdy potrzebujesz sprawdzić prototyp obiektu przed zrobieniem czegoś z nim.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-05 11:10:47
Właśnie znalazłem aplikację w realnym świecie i myślę, że będę z niej częściej korzystać.
Jeśli używasz zdarzeń jQuery, czasami chcesz napisać bardziej ogólną funkcję, która może być również wywoływana bezpośrednio (bez zdarzenia). Możesz użyć instanceof
, aby sprawdzić, czy pierwszy parametr twojej funkcji jest instancją jQuery.Event
i odpowiednio zareagować.
var myFunction = function (el) {
if (el instanceof $.Event)
// event specific code
else
// generic code
};
$('button').click(recalc); // Will execute event specific code
recalc('myParameter'); // Will execute generic code
W moim przypadku funkcja potrzebna do obliczenia czegoś albo dla wszystkich (poprzez kliknięcie przycisku), albo tylko dla jednego konkretnego elementu. Kod Użyłem:
var recalc = function (el) {
el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
// calculate...
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-26 12:18:16