Quel est l'opérateur instanceof en JavaScript?
-
20-09-2019 - |
Question
Le mot-clé instanceof
JavaScript peut être assez déroutant quand il est d'abord rencontré, que les gens ont tendance à penser que JavaScript n'est pas un langage de programmation orienté objet.
- Qu'est-ce?
- Quels problèmes faut-il résoudre?
- Quand est-il approprié et quand ne pas?
La solution
instanceof
L'opérande côté gauche (LHS) est l'objet réel testé à l'opérande Côté droit (RHS) qui est le constructeur réelle d'une classe. La définition de base est:
Checks the current object and returns true if the object
is of the specified object type.
Voici quelques bons exemples et voici un exemple pris directement à partir de site développeur de Mozilla :
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)
Une chose intéressante à mentionner est instanceof
évalue true si l'objet hérite du prototype du classe:
var p = new Person("Jon");
p instanceof Person
C'est p instanceof Person
est vrai que p
hérite de Person.prototype
.
Par la demande de l'OP
J'ai ajouté un petit exemple avec quelques exemples de code et une explication.
Lorsque vous déclarez une variable que vous lui donnez un type spécifique.
Par exemple:
int i;
float f;
Customer c;
Le spectacle ci-dessus vous quelques variables, à savoir i
, f
et c
. Les types sont integer
, float
et un Customer
défini par l'utilisateur type de données. Les types tels que ci-dessus pourraient être pour toutes les langues, pas seulement JavaScript. Cependant, avec JavaScript lorsque vous déclarez une variable que vous ne définissez pas explicitement un type, var x
, x peut être un nombre / string / un type de données défini par l'utilisateur. Alors qu'est-ce instanceof
fait est-il vérifie l'objet pour voir si elle est du type spécifié ci-dessus afin de prendre l'objet Customer
nous pourrions faire:
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!
Au-dessus, nous avons vu que c
a été déclarée avec le Customer
de type. Nous avons new'd et vérifié si elle est de type Customer
ou non. Bien sûr, est-il retourne vrai. Ensuite, en utilisant encore l'objet Customer
, nous vérifions si elle est un String
. Non, certainement pas un String
nous newed un objet Customer
pas un objet String
. Dans ce cas, il retourne faux.
Il est vraiment aussi simple que cela!
Autres conseils
Il y a un aspect important de InstanceOf qui ne semble pas être couvert dans l'un des commentaires jusqu'ici: l'héritage. Une variable qui est évaluée par l'utilisation de instanceof pourrait retourner vrai pour plusieurs « types » en raison de l'héritage prototypal.
Par exemple, nous allons définir un type et un sous-type:
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 = Object.create(Foo.prototype); // Inherit prototype
SubFoo.prototype.constructor = SubFoo;
Maintenant que nous avons deux ou trois « classes » permet de faire certains cas, et savoir ce qu'ils sont les cas de:
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
Voir cette dernière ligne? Tous les appels « nouveaux » à une fonction retourne un objet qui hérite de l'objet. Cela est vrai même en utilisant un raccourci de création d'objets:
alert(
"Q: Is {} an instance of Object? "
+ "A: " + ( {} instanceof Object )
); // -> true
Et la « classe » eux-mêmes définitions? Que sont-ils des cas de?
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
Je pense que la compréhension que tout objet peut être une instance de multiples types est important, puisque vous mon (à tort) supposons que vous pouvez faire la différence entre, par exemple et de l'objet et une fonction par l'utilisation de instanceof
. Comme ce dernier exemple montre clairement une fonction un objet.
Il est également important si vous utilisez des modèles d'héritage et que vous voulez confirmer la descendance d'un objet par des méthodes autres que le canard dactylographie.
L'espoir qui aide qui entend explorer instanceof
.
Les autres réponses ici sont corrects, mais ils ne reçoivent pas la façon dont instanceof
fonctionne réellement, ce qui peut intéresser certains avocats de la langue là-bas.
Chaque objet JavaScript a un prototype, accessible par la propriété __proto__
. Les fonctions ont également une propriété prototype
, qui est le __proto__
initial pour tous les objets créés par eux. Lorsqu'une fonction est créée, elle est donnée un objet unique pour prototype
. L'opérateur utilise cette instanceof
unique pour vous donner une réponse. Voici ce que instanceof
pourrait ressembler si vous l'avez écrit en fonction.
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__;
}
}
Ceci est essentiellement paraphrase édition ECMA-262 5.1 (également connu sous le nom ES5), section 15.3.5.3.
Notez que vous pouvez réaffecter un objet à la propriété prototype
d'une fonction, et vous pouvez réattribuer après sa construction, la propriété __proto__
d'un objet. Cela vous donnera des résultats intéressants:
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
Je pense qu'il est intéressant de noter que instanceof est définie par l'utilisation du mot-clé « nouveau » lors de la déclaration de l'objet. Dans l'exemple de 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)
Ce qu'il ne mentionne pas est ceci:
var color1 = String("green");
color1 instanceof String; // returns false
Spécification « nouveau » en fait copié l'état final de la fonction constructeur String dans le var color1, plutôt que de la mise à la valeur de retour. Je pense que cette montre mieux ce que le nouveau mot-clé fait;
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'
Utilisation de « nouveau » attribue la valeur de « cette » à l'intérieur de la fonction à la var déclarée, sans utiliser affecte la valeur de retour à la place.
Et vous pouvez l'utiliser pour le traitement des erreurs et le débogage, comme ceci:
try{
somefunction();
}
catch(error){
if (error instanceof TypeError) {
// Handle type Error
} else if (error instanceof ReferenceError) {
// Handle ReferenceError
} else {
// Handle all other error types
}
}
//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);
Qu'est-ce?
Javascript est un langage prototypique qui signifie qu'il utilise des prototypes « héritage ». les tests d'opérateur instanceof
si un prototype
de fonction constructeur de propertype est présent dans la chaîne de __proto__
d'un objet. Cela signifie qu'il fera ce qui suit (en supposant que TestObj est un objet de fonction):
obj instanceof testObj;
- Vérifiez si le prototype de l'objet est égal au prototype du constructeur:.
obj.__proto__ === testObj.prototype
>> si cela esttrue
instanceof
retourneratrue
- monterai la chaîne de prototype. Par exemple:.
obj.__proto__.__proto__ === testObj.prototype
>> si cela esttrue
instanceof
retourneratrue
- répétera l'étape 2 jusqu'à ce que le prototype complet de l'objet est inspecté. Si nulle part sur la chaîne de prototype de l'objet est apparié avec
testObj.prototype
alors opérateurinstanceof
retournerafalse
.
Exemple:
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
Quels problèmes faut-il résoudre?
Il a résolu le problème de vérifier facilement si un objet dérive d'un certain prototype. Par exemple, lorsqu'une fonction d'un objet qui reçoit peut avoir différents prototypes. Puis, avant d'utiliser des méthodes de la chaîne prototype, nous pouvons utiliser l'opérateur instanceof
pour vérifier si les ces méthodes sont l'objet.
Exemple:
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);
Ici, dans la fonction talk()
premier est vérifié si le prototype est situé sur l'objet. Après cela, la méthode appropriée est choisi pour exécuter. Ne pas faire cette vérification pourrait donner lieu à l'exécution d'une méthode qui n'existe pas et donc une erreur de référence.
Quand est-il approprié et quand ne pas?
Nous avons un peu déjà allés à ce sujet. Utilisez-le quand vous avez besoin de vérifier le prototype d'un objet avant de faire quelque chose avec elle.
Sur la question "Quand est-il approprié et quand ne pas?", Mes 2 cents:
instanceof
est rarement utile dans le code de production, mais utile dans les tests où vous voulez affirmer que votre code renvoie / crée des objets des types corrects. En étant explicite sur les types d'objets que votre code Reprise / création, vos tests deviennent plus puissants comme un outil pour comprendre et documenter votre code.
instanceof
est juste du sucre syntaxique pour 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
dépend juste du prototype d'un constructeur d'un objet.
Un constructeur est juste une fonction normale. Au sens strict, il est un objet de fonction, puisque tout est un objet en Javascript. Et cet objet de fonction a un prototype, parce que chaque fonction a un prototype.
Un prototype est juste un objet normal, qui est situé dans la chaîne de prototype d'un autre objet. Cela veut dire être dans la chaîne de prototype d'un autre objet fait l'objet d'un 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
L'opérateur instanceof
doit être évitée car elle feint des classes, qui n'existent pas en Javascript. Malgré le mot-clé class
pas ES2015 non plus, puisque class
est à nouveau juste du sucre syntaxique pour ... mais c'est une autre histoire.
Je viens de trouver une application dans le monde réel et utilisera plus souvent maintenant, je pense.
Si vous utilisez des événements jQuery, parfois vous voulez écrire une fonction plus générique qui peut également être appelé directement (sans événement). Vous pouvez utiliser instanceof
pour vérifier si le premier paramètre de votre fonction est une instance de jQuery.Event
et réagir de manière appropriée.
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
Dans mon cas, la fonction nécessaire pour calculer quelque chose soit pour tous (par événement clic sur un bouton) ou un seul élément spécifique. Le code je:
var recalc = function (el) {
el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el);
// calculate...
};