Quand un catch attrape une erreur, il ne sait pas encore de quelle sorte elle est. Un problème de réseau et une donnée invalide n'appellent pas la même réaction, et le code doit pouvoir les distinguer avant de décider quoi faire.
instanceof sert exactement à cela : identifier la nature d'un objet quand typeof se contente de répondre 'object'.
Définition
instanceof renvoie true si l'objet placé à sa gauche a été construit à partir de la classe ou de la fonction placée à sa droite, directement ou par héritage.
class Animal {}
class Chien extends Animal {}
const rex = new Chien();
rex instanceof Chien; // true
rex instanceof Animal; // true
rex instanceof Object; // true
rex instanceof Array; // falseUn objet est donc reconnu comme une instance de sa classe, mais aussi de toutes celles dont elle hérite via extends. C'est ce qui permet d'écrire un test large ou un test précis selon le besoin.
Le cas d'usage le plus fréquent
Trier les erreurs dans un try reste l'emploi le plus courant, parce que toutes les erreurs partagent le même type mais pas la même signification.
try {
await enregistrer(formulaire);
} catch (erreur) {
if (erreur instanceof TypeError) {
console.error('Bug côté code :', erreur.message);
} else {
console.error('Échec de l\'enregistrement');
}
}La même logique s'applique aux classes que vous écrivez : une erreur métier créée avec class et extends depuis Error se reconnaît ensuite en une ligne.
Les trois cas où il se trompe
- Les valeurs de base ne sont pas des objets.
'abc' instanceof Stringvautfalse, alors que le texte est bien une chaîne. Pour ces valeurs, typeof est le bon outil. - Les frontières entre contextes. Un tableau venu d'un cadre inclus, ou d'un contexte créé avec le module
vmde Node, n'est pas construit à partir du même Array (tableau) : le test échoue alors que la valeur est bien un tableau.Array.isArray()ne souffre pas de ce défaut. - Un objet ordinaire ne dit rien. Tout ce qui vient de JSON est une instance d'
Object, ce qui ne renseigne sur rien. Une donnée reçue du réseau se vérifie par son contenu, pas par sa classe.
La valeur à droite doit être une classe ou une fonction. valeur instanceof 'Chien' lève une erreur, car un texte ne peut pas servir de constructeur : c'est le nom de la classe qu'il faut écrire, sans guillemets.
Questions fréquentes
Fonctionne-t-il avec les anciennes fonctions constructeur ?
Oui, et c'est même son usage d'origine. Une fonction appelée avec new produit un objet reconnu par instanceof, exactement comme une classe. Les classes ne sont d'ailleurs, sur ce point, qu'une écriture plus lisible du même mécanisme.
Pourquoi ne pas comparer constructor.name à la place ?
Parce que ce nom est une chaîne, qui ne dit rien de l'héritage et disparaît souvent à la minification du code envoyé au navigateur. instanceof remonte la vraie filiation de l'objet et ne dépend pas des noms conservés dans le fichier final.
instanceof ou typeof, lequel utiliser ?
Les deux répondent à des questions différentes. typeof traite les valeurs de base, texte, nombre, booléen, alors qu'instanceof traite les objets construits à partir d'une classe. Dans une fonction qui accepte des entrées variées, on utilise souvent les deux à la suite, en commençant par le test le plus large.