Quel est l'instance de l'opérateur en JavaScript?

Le mot-clé instanceof dans JavaScript peut être assez déroutant lors de sa première rencontre, car les gens ont tendance à penser que JavaScript n'est pas un langage de programmation orienté objet.

  • Qu'Est-ce que c'est?
  • Quels problèmes résolvent-ils?
  • Quand est-il approprié et quand pas?

    exemple de

    L'opérande côté gauche (LHS) est l'objet réel testé dans l'opérande côté droit (RHS) qui est le constructeur réel 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 de bons exemples et voici un exemple pris directement à partir du site de 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 qui vaut la peine d'être mentionnée est instanceof s'avère vrai si l'objet hérite du prototype de la classe:

     var p = new Person("Jon"); p instanceof Person 

    C'est p instanceof Person est vraie puisque p hérite de Person.prototype .

    Selon la demande de l'OP

    J'ai ajouté un petit exemple avec un exemple de code et une explication.

    Lorsque vous déclarez une variable, vous lui donnez un type spécifique.

    Par exemple:

     int i; float f; Customer c; 

    Ce qui précède vous montre quelques variables, à savoir i , f et c . Les types sont integer , float et un type de données Customer défini par l'utilisateur. Les types tels que ceux ci-dessus pourraient être pour n'importe quelle langue, pas seulement JavaScript. Cependant, avec JavaScript lorsque vous déclarez une variable, vous ne définissez pas explicitement un type, var x , x pourrait être un nombre / chaîne / un type de données défini par l'utilisateur. Donc, quelle instanceof fait, vérifie-t-il l'objet pour voir s'il est du type spécifié, donc, en haut, prenant 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 été déclaré avec le type Customer . Nous l'avons New'd et vérifié si c'est du type Customer ou non. Bien sûr, il revient vrai. Ensuite, nous utilisons toujours l'objet Customer , nous vérifions s'il s'agit d'une String . Non, certainement pas une String nous avons créé un objet Customer non un objet String . Dans ce cas, il renvoie faux.

    C'est aussi simple que ça!

    Il y a une facette importante à l'instance qui ne semble pas être couverte dans aucun des commentaires jusqu'à présent: l'héritage. Une variable évaluée par l'utilisation d'instanceof pourrait être réelle pour plusieurs "types" en raison de l'héritage prototypique.

    Par exemple, définissons 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 = new Foo(); // Inherit prototype 

    Maintenant que nous avons quelques "classes", nous allons faire quelques exemples et découvrez de quoi ils sont:

     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 

    Voyez cette dernière ligne? Tous les "nouveaux" appels à une fonction renvoient un objet qui hérite d'Object. Cela est vrai même lorsque vous utilisez un raccourci de création d'objet:

     alert( "Q: Is {} an instance of Object? " + "A: " + ( {} instanceof Object ) ); // -> true 

    Et quelles sont les définitions de «classe» elles-mêmes? De quoi en sont-ils?

     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 n'importe quel objet peut être une instance de types MULTIPLES est importante, puisque vous mon (incorrectement) supposons que vous pourriez différencier, dire et objet et une fonction à l'aide de instanceof . Comme ce dernier exemple montre clairement qu'une fonction est un objet.

    Ceci est également important si vous utilisez des modèles d'héritage et que vous souhaitez confirmer la progéniture d'un objet par des méthodes autres que le typage de canard.

    J'espère que cela permet à quiconque d'explorer l' instanceof .

    Les autres réponses ici sont correctes, mais elles n'interviennent pas sur la manière dont fonctionne actuellement, ce qui pourrait intéresser certains avocats de la langue là-bas.

    Chaque objet en JavaScript comporte un prototype accessible via la propriété __proto__ . Les fonctions ont également un prototype propriété, qui est la __proto__ initiale pour tous les objets créés par eux. Lorsqu'une fonction est créée, il s'agit d'un objet unique pour le prototype . L' instanceof opérateur utilise cette singularité pour vous donner une réponse. Voici comment pourrait ressembler un instanceof si vous l'avez écrit comme une 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 paraphrase essentiellement l'édition ECMA-262 5.1 (également connue sous le nom de ES5), section 15.3.5.3.

    Notez que vous pouvez réaffecter tout objet à la propriété prototype une fonction et que vous pouvez réaffecter la propriété __proto__ un objet après sa construction. 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 vaut la peine 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 n'a pas mentionné, c'est ceci;

     var color1 = String("green"); color1 instanceof String; // returns false 

    La spécification de "nouveau" a effectivement copié l'état final de la fonction du constructeur de chaîne dans la couleur1 var, plutôt que de l'ajuster à la valeur de retour. Je pense que cela montre mieux ce que fait le nouveau mot-clé;

     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' 

    L'utilisation de "nouveau" attribue la valeur de "ceci" à l'intérieur de la fonction à la var déclarée, alors qu'elle ne l'utilise pas affecte la valeur de retour à la place.

    Et vous pouvez l'utiliser pour la gestion 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); 

    Sur la question "Quand est-il approprié et quand pas?", Mes 2 cents:

    instanceof est rarement utile dans le code de production, mais utile dans les tests où vous souhaitez affirmer que votre code renvoie / crée des objets des types corrects. En étant explicite sur les types d'objets que votre code renvoie / crée, vos tests deviennent plus puissants en tant qu'outil de compréhension et de documentation de votre code.

    Je viens de trouver une application réelle et je l'utiliserai plus souvent maintenant, je pense.

    Si vous utilisez des événements jQuery, vous souhaitez parfois écrire une fonction plus générique qui peut également être appelée 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 (via un événement de clic sur un bouton) ou un seul élément spécifique. Le code que j'ai utilisé:

     var recalc = function (el) { el = (el == undefined || el instanceof $.Event) ? $('span.allItems') : $(el); // calculate... }; 

    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 simplement du prototype d'un constructeur d'un objet.

    Un constructeur n'est qu'une fonction normale. À proprement parler, c'est un objet fonction, car tout est un objet en Javascript. Et cet objet de fonction a un prototype, car chaque fonction possède un prototype.

    Un prototype n'est qu'un objet normal, qui se trouve dans la chaîne prototype d'un autre objet. Cela signifie être dans la chaîne prototype d'un autre objet qui fait un objet à 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' instanceof opérateur doit être évitée car elle falsifie les classes, qui n'existent pas en Javascript. Bien que le mot class clé de la class ne soit pas non plus dans ES2015, puisque la class est de nouveau simplement du sucre syntaxique pour … mais c'est une autre histoire.