W3docs

JavaScript — Étendre les classes intégrées

Apprenez à étendre les classes intégrées JavaScript comme Array, Map, Set et Error pour ajouter des comportements personnalisés.

Les classes intégrées telles que Array, Map, Set et Error sont de vraies classes sous le capot, et vous pouvez donc les étendre avec extends exactement comme n'importe quelle classe que vous écrivez vous-même. La sous-classe hérite de toutes les méthodes du parent et peut ajouter de nouvelles méthodes, modifier des comportements ou stocker un état supplémentaire. C'est une manière propre de construire une collection spécialisée (un array capable de se sommer lui-même, une map avec des valeurs par défaut) ou un type d'erreur spécifique à un domaine — sans toucher au prototype global, ce qui constitue l'alternative plus risquée décrite dans JavaScript : Prototypes natifs.

Ce chapitre couvre la syntaxe de base, la façon dont les méthodes intégrées retournent des instances de votre sous-classe, comment Symbol.species vous permet de contrôler cela, l'extension de Error pour des types d'erreurs personnalisés, ainsi que les mises en garde à connaître avant d'utiliser cette technique. Si vous débutez avec extends et super, lisez d'abord JavaScript : Héritage de classe.

Syntaxe et exemple de base

La syntaxe est identique à l'extension de n'importe quelle autre classe :

class CustomClass extends BuiltInClass {
  // New methods and properties to extend the built-in class
}

Si votre sous-classe définit un constructeur, vous devez appeler super() avant d'utiliser this. Cela permet à la classe parente d'initialiser correctement son état interne et ses structures natives — pour Array et Map, cet état interne est ce qui les fait fonctionner.

Étendons la classe Array avec une méthode qui additionne tous les éléments :

javascript— editable

L'instance se comporte comme un array complet — l'indexation, length, l'itération et toutes les méthodes de Array fonctionnent — plus la méthode sum() que vous avez ajoutée.

⚠️ Remarque : Lorsque vous étendez Array, sachez que la propriété length se comporte de manière particulière en JavaScript. Dans certains environnements, length peut ne pas se synchroniser automatiquement avec la taille réelle de l'array lors de l'utilisation de certaines méthodes natives. Testez soigneusement ou envisagez la composition si un suivi précis de la longueur est essentiel.

Les méthodes intégrées retournent des instances de votre sous-classe

C'est ce qui rend l'extension de Array réellement puissante : les méthodes comme map, filter et slice qui retournent un nouvel array renvoient une instance de votre sous-classe, et non un Array ordinaire. Cela signifie que le nouvel array possède toujours vos méthodes personnalisées.

javascript— editable

En interne, le moteur décide quel constructeur utiliser grâce à un getter statique spécial nommé Symbol.species. Par défaut, Symbol.species retourne la sous-classe elle-même, c'est pourquoi filter a produit un ExtendedArray ci-dessus.

Contrôler le type de retour avec Symbol.species

Parfois, vous souhaitez l'inverse : les méthodes comme map et filter doivent retourner des arrays ordinaires, tandis que new ExtendedArray(...) vous donne toujours votre sous-classe. Surchargez Symbol.species pour pointer vers la classe de base :

javascript— editable

Maintenant, arr est un PowerArray doté de votre méthode isEmpty(), mais filter retourne un Array ordinaire qui ne possède plus cette méthode. Utilisez ceci lorsque votre sous-classe ajoute un état dans son constructeur que les arrays dérivés ne doivent pas hériter. Symbol.species est également respecté par Map, Set, ArrayBuffer et Promise.

Améliorer la classe String

La classe String est un autre objet intégré fondamental qui peut être étendu avec des assistants supplémentaires de manipulation de chaînes.

Ajouter une fonction de retournement

javascript— editable

⚠️ Remarque : L'extension de String est généralement déconseillée en raison des particularités de la coercition primitive-vers-objet en JavaScript, qui peuvent provoquer un comportement inattendu avec les méthodes natives. Pour la manipulation de chaînes, préférez les fonctions utilitaires ou la composition à l'héritage.

Personnaliser la classe Map

La classe Map en JavaScript représente une collection d'éléments de données associés à des clés, offrant un moyen de stockage de données plus avancé et flexible que les objets. Étendre la classe Map nous permet d'introduire des comportements plus spécialisés.

Implémenter une valeur par défaut

Étendre Map pour retourner une valeur par défaut si la clé n'existe pas. Notez comment la méthode get surchargée appelle super.get(key) pour accéder à la vraie recherche Map :

javascript— editable

Étendre la classe Error

Un usage courant et pratique de cette fonctionnalité est la création de types d'erreurs personnalisés. La sous-classification de Error vous donne une erreur nommée que vous pouvez identifier avec instanceof, tout en restant une vraie Error (elle porte donc un message, une stack et fonctionne avec try...catch).

javascript— editable

Définir this.name est important — cela contrôle la façon dont l'erreur s'affiche et vous permet de distinguer votre type d'erreur d'une erreur générique. Pour un traitement plus approfondi, incluant la construction d'une hiérarchie de classes d'erreurs, consultez JavaScript : Erreurs personnalisées, Extension d'Error.

Bonnes pratiques et considérations

Bien que l'extension des classes intégrées ouvre un vaste champ de possibilités, il est essentiel de respecter les bonnes pratiques pour assurer la maintenabilité et la compatibilité du code.

  • Évitez de surcharger les méthodes existantes : Étendre les classes intégrées en ajoutant de nouvelles méthodes est généralement sûr. Cependant, surcharger des méthodes existantes peut entraîner des comportements imprévisibles et des problèmes de compatibilité.
  • Utilisez pour des besoins spécifiques : Étendez les classes intégrées uniquement lorsqu'il y a un avantage ou une nécessité clairement identifiés. Évitez les extensions inutiles qui pourraient complexifier votre base de code.
  • Préférez la composition ou les fonctions utilitaires : En JavaScript moderne, étendre les classes intégrées est souvent inutile. L'utilisation de fonctions d'assistance ou la composition offre généralement des résultats plus propres et plus prévisibles sans modifier les éléments internes des sous-classes natives.
  • Documentez clairement les extensions : Assurez-vous que toute extension des classes intégrées est bien documentée dans votre base de code afin d'éviter toute confusion parmi les autres développeurs.

Les méthodes statiques sont aussi héritées

Lorsque vous utilisez extends sur une classe intégrée, la sous-classe hérite également des méthodes statiques du parent. Ainsi, ExtendedArray.from(...) et ExtendedArray.isArray(...) sont disponibles, et les méthodes de fabrique statiques comme Array.from produisent des instances de la sous-classe. Cela reflète le comportement normal de l'héritage de classe — consultez JavaScript : Propriétés et méthodes statiques pour savoir comment les membres statiques sont hérités.

Conclusion

Étendre les classes intégrées est une manière propre d'ajouter un comportement ciblé aux objets natifs — un array qui se somme, une map avec valeurs par défaut, une erreur nommée — sans modifier les prototypes globaux. L'idée clé à retenir est que les méthodes intégrées dérivées retournent par défaut des instances de votre sous-classe, et Symbol.species est le levier pour modifier ce comportement. Optez pour l'héritage lorsqu'une véritable relation "est-un" existe ; sinon, préférez les fonctions utilitaires ordinaires ou la composition.

Pratique

Pratique
Quelles affirmations sont exactes concernant l'extension des classes intégrées en JavaScript ?
Quelles affirmations sont exactes concernant l'extension des classes intégrées en JavaScript ?
Was this page helpful?