JavaScript instanceof
Découvrez l'opérateur instanceof en JavaScript pour vérifier le type d'un object à l'exécution, gérer l'héritage et implémenter le polymorphisme.
Introduction à l'opérateur instanceof
L'opérateur instanceof en JavaScript est un outil puissant permettant de déterminer si un object est une instance d'une classe ou d'une fonction constructeur spécifique. Il aide les développeurs à vérifier le type d'un object à l'exécution, facilitant ainsi la vérification de type et la mise en œuvre efficace du polymorphisme. Cet opérateur parcourt la chaîne de prototypes d'un object en la comparant au prototype d'une fonction constructeur, et retourne un résultat boolean indiquant si l'object hérite de ce prototype.
Syntaxe et utilisation
La syntaxe de l'opérateur instanceof est simple :
object instanceof ConstructorOù object est l'object à tester contre le Constructor. L'opérateur retourne true si l'object est une instance du Constructor ou en hérite ; sinon, il retourne false.
Exemple de code : utilisation de base
Considérons l'exemple suivant où nous définissons une classe Vehicle et en créons une instance :
Applications avancées
Au-delà de la vérification de type basique, l'opérateur instanceof joue un rôle crucial dans des scénarios plus complexes impliquant l'héritage et le polymorphisme. Explorons un scénario avec l'héritage :
Exemple de code : héritage
Cet exemple illustre comment instanceof confirme que myCar est non seulement une instance de Car, mais aussi une instance de Vehicle, démontrant la capacité de l'opérateur à reconnaître la chaîne d'héritage.
Comment instanceof parcourt la chaîne de prototypes
instanceof ne vérifie pas directement quel constructeur a créé l'object. Il remonte plutôt la chaîne de prototypes de l'object et pose la question : Constructor.prototype apparaît-il quelque part dans cette chaîne ? Dès qu'une correspondance est trouvée, il retourne true ; s'il atteint la fin de la chaîne (null) sans correspondance, il retourne false.
De ce fait, vous pouvez modifier ou casser un résultat instanceof en réassignant la chaîne de prototypes — la vérification porte uniquement sur l'appartenance à la chaîne, et non sur le constructeur exécuté. Pour comprendre la chaîne elle-même, consultez L'héritage prototypal et Syntaxe de base des classes.
Personnaliser instanceof avec Symbol.hasInstance
Vous pouvez remplacer ce que retourne obj instanceof Constructor en définissant une méthode statique [Symbol.hasInstance] sur le constructeur. Lorsqu'elle est présente, instanceof l'appelle avec l'opérande gauche et utilise son résultat boolean, ignorant entièrement la chaîne de prototypes.
Cela est utile pour le duck-typing — traiter tout object qui « semble correct » comme membre d'un type — sans le forcer à traverser la hiérarchie de classes.
instanceof vs typeof vs constructor
Ces trois outils répondent à des questions différentes, et choisir le mauvais est une source courante de bugs.
typeofretourne une string pour les catégories de types primitifs. Il est idéal pour les primitives, mais retourne"object"pour presque tout (arrays,null, dates, objets simples), et ne peut donc pas distinguer les types d'objets.instanceofteste l'appartenance à la chaîne de prototypes et respecte l'héritage — mais il échoue entre les realms (voir ci-dessous) et ne fonctionne pas avec les primitives.obj.constructorpointe vers la fonction qui a créé l'object, mais c'est simplement une propriété modifiable qui ne reflète que la classe la plus spécifique, pas toute la chaîne.
Les constructeurs natifs utilisés ci-dessus sont abordés dans Les prototypes natifs.
La mise en garde des realms (iframe/window)
Chaque contexte de navigation — chaque iframe ou fenêtre popup — possède son propre ensemble de constructeurs natifs ainsi que ses propres Array.prototype, Object.prototype, etc. Un array créé dans un iframe est un vrai array, mais il n'hérite pas du Array.prototype de votre fenêtre. En conséquence, arrayFromIframe instanceof Array retourne false dans la fenêtre parente, même si la valeur est bien un array. C'est la raison la plus courante pour laquelle instanceof « ment ».
Pour les valeurs susceptibles de traverser les realms, préférez des vérifications agnostiques au realm, comme Array.isArray(value).
Tags de type fiables avec Object.prototype.toString
Lorsque vous avez besoin d'une vérification de type robuste, compatible avec les realms et fonctionnant également avec les primitives, Object.prototype.toString retourne une string de tag interne sous la forme [object Type]. Elle ne peut pas être trompée par des prototypes réassignés comme peut l'être constructor, et elle fonctionne entre les realms.
Utilisez-la via .call(value) afin que la valeur devienne this. Une classe peut même contrôler son propre tag grâce à la propriété Symbol.toStringTag.
Bonnes pratiques et considérations
Bien que l'opérateur instanceof soit indispensable, il est essentiel de l'utiliser avec discernement :
- Sensibilité à la chaîne de prototypes : L'opérateur
instanceofrepose sur la chaîne de prototypes, ce qui signifie que les modifications apportées au prototype d'un object peuvent affecter le résultat des vérificationsinstanceof. - Utilisation dans le polymorphisme : Il est particulièrement utile dans les scénarios où un comportement polymorphique est souhaité, permettant un code flexible capable de gérer des objets de différents types de manière unifiée.
- Problèmes inter-frames : Soyez prudent lorsque vous utilisez
instanceofavec des objets provenant de contextes JavaScript différents (par exemple, des iframes ou des fenêtres différentes), car chaque contexte possède sa propre chaîne de prototypes unique.
Exemple pratique : polymorphisme
Voici comment vous pourriez utiliser instanceof pour implémenter un comportement polymorphique :
Conclusion
Comprendre et utiliser efficacement l'opérateur instanceof est essentiel pour maîtriser les aspects de la programmation orientée object en JavaScript. Il aide non seulement à la vérification de type et à l'assurance de l'exactitude de votre code, mais vous permet également d'écrire un code plus flexible et maintenable grâce au polymorphisme. En intégrant judicieusement l'opérateur instanceof dans vos pratiques de développement, vous pouvez considérablement renforcer la robustesse et la scalabilité de vos applications JavaScript.