W3docs

Héritage de classes JavaScript

Apprenez l'héritage de classes JavaScript avec extends et super : la chaîne de prototypes, la surcharge de méthodes, super(), les classes natives et les méthodes statiques.

Introduction à l'héritage de classes JavaScript

L'héritage de classes est un concept fondamental de la programmation orientée objet qui permet à une classe d'hériter des propriétés et des méthodes d'une autre classe. En JavaScript, l'héritage de classes est implémenté à l'aide du mot-clé extends, offrant un moyen de créer une classe dérivée qui hérite d'une classe de base.

Pour plus d'informations sur la syntaxe de base, consultez JavaScript : Classes et syntaxe de base.

Ce chapitre explique comment créer des classes dérivées, surcharger des méthodes et des propriétés, appeler le parent avec super, étendre des classes natives comme Array, et hériter de méthodes statiques — ainsi que la chaîne de prototypes qui rend tout cela possible en coulisses.

Fonctionnement de l'héritage : la chaîne de prototypes

Le mot-clé class est du sucre syntaxique par-dessus l'héritage prototypal de JavaScript. Lorsque vous écrivez class Circle extends Shape, le moteur établit deux liens :

  • Circle.prototype.__proto__ === Shape.prototype — ainsi les méthodes d'instance remontent la chaîne.
  • Circle.__proto__ === Shape — ainsi les méthodes statiques sont également héritées.

Lorsque vous lisez une propriété ou appelez une méthode sur un object, le moteur regarde d'abord l'object lui-même. Si elle n'est pas trouvée, il remonte la chaîne de prototypes — vers Circle.prototype, puis Shape.prototype, puis Object.prototype, puis null — en s'arrêtant à la première correspondance. C'est précisément pour cela qu'une instance de Circle peut appeler une méthode définie sur Shape.

javascript— editable

Object.getPrototypeOf(obj) retourne le maillon suivant dans la chaîne (la façon standard et préconisée de l'inspecter). L'accesseur historique obj.__proto__ pointe vers le même object. Comprendre cette chaîne explique tout ce qui suit : la surcharge fonctionne parce qu'un prototype plus proche masque un prototype plus éloigné, et super fonctionne parce qu'il saute explicitement au prototype parent.

Créer une classe dérivée

Pour créer une classe qui hérite d'une autre, on utilise le mot-clé extends :

javascript— editable

Dans cet exemple, Circle étend Shape, ce qui signifie qu'elle hérite des propriétés et méthodes de Shape, tout en fournissant ses propres méthodes. Notez que Circle ne définit pas son propre constructeur. En JavaScript, les classes dérivées sans constructeur explicite appellent automatiquement super() avec les mêmes arguments passés au constructeur de la classe dérivée.

Surcharger des méthodes

Les classes dérivées peuvent surcharger les méthodes de leurs classes de base pour fournir un comportement spécifique à la sous-classe.

javascript— editable

Ici, Circle surcharge la méthode print pour refléter son type spécifique.

Appeler les méthodes parentes avec super

Vous pouvez également appeler une méthode de la classe parente depuis la classe dérivée en utilisant super.methodName(). C'est utile lorsque vous souhaitez étendre le comportement du parent plutôt que de le remplacer complètement.

javascript— editable

Ici, super.print() exécute la logique du parent avant d'ajouter la sortie spécifique à la sous-classe.

Un exemple concret de surcharge : calculer une aire

La surcharge est particulièrement utile lorsque chaque sous-classe a besoin d'un comportement vraiment différent. Ici, une Shape de base définit l'interface partagée, et chaque sous-classe surcharge area() avec son propre calcul. L'appel de area() sur un Circle se résout vers Circle.prototype.area, qui masque la version de base.

javascript— editable

Notez que describe() est défini uniquement sur Shape, pourtant il appelle this.area() et obtient l'implémentation de la sous-classe. C'est la chaîne de prototypes à l'œuvre : this fait toujours référence à l'instance réelle, donc la recherche de méthode commence à partir de Circle ou Rectangle.

Surcharger des propriétés et lire super.prop

super n'est pas limité aux méthodes — vous pouvez lire une propriété définie sur le prototype parent avec super.prop, ce qui est pratique quand une sous-classe veut s'appuyer sur le getter d'un parent plutôt que de le remplacer.

javascript— editable

Accéder au constructeur parent : le mot-clé super

Lorsqu'une classe étend une autre classe, le constructeur de la classe dérivée doit appeler le constructeur du parent avec super() avant de pouvoir utiliser this. Voici comment super est utilisé dans les constructeurs pour s'assurer que la classe parente est initialisée :

javascript— editable

Pourquoi super() doit s'exécuter avant this

Dans une classe dérivée, l'instance n'est pas créée tant que super() ne s'est pas exécuté — c'est le travail du constructeur parent. Jusqu'alors, this est dans un état non initialisé, donc y accéder (lire, assigner, ou même retourner l'object implicitement) lance une ReferenceError. Il s'agit d'une règle du langage, non d'une préférence de style.

javascript— editable

Une règle connexe : si une classe dérivée définit un constructeur, elle doit appeler super() quelque part avant de se terminer, ou la même ReferenceError est lancée. (Une classe dérivée sans constructeur explicite convient — JavaScript insère constructor(...args) { super(...args); } pour vous.) Une fois que super() retourne, this est entièrement initialisé et prêt à l'emploi.

Hériter des méthodes statiques

Les membres statiques appartiennent à la classe elle-même, pas aux instances. Parce que extends lie également Circle.__proto__ à Shape, les classes dérivées héritent des méthodes statiques et peuvent les appeler directement. Pour plus d'informations sur leur déclaration, consultez Propriétés et méthodes statiques JavaScript.

javascript— editable

À l'intérieur d'une méthode statique, this fait référence à la classe sur laquelle elle a été invoquée, donc Shape.create appelé en tant que Circle.create construit un Circle.

Héritage multi-niveaux

Les chaînes peuvent avoir plus de deux niveaux. La recherche de méthode remonte simplement plus loin dans la chaîne de prototypes, et super fait toujours référence au prototype un niveau au-dessus de la classe où la méthode est définie.

javascript— editable

Étendre les classes natives

Vous pouvez étendre des classes natives telles que Array, Error ou Map pour créer des versions spécialisées qui conservent tout le comportement natif tout en ajoutant le vôtre.

javascript— editable

Le piège de Symbol.species. Les méthodes comme map, filter et slice retournent une nouvelle collection. Par défaut, elles retournent une instance de votre sous-classe (MyArray), pas un Array ordinaire — ce qui est généralement correct, mais peut surprendre du code qui attend un vrai Array. Vous pouvez revenir aux tableaux ordinaires en surchargeant le getter statique Symbol.species.

javascript— editable

Pour combiner des comportements provenant de plusieurs sources (JavaScript ne prend pas en charge l'héritage multiple), consultez Les mixins JavaScript.

Résumé

Points clés à retenir :

  • Utilisez extends pour dériver une classe ; cela lie à la fois la chaîne de prototypes (méthodes d'instance) et la classe elle-même (méthodes statiques) au parent.
  • La recherche de méthode et de propriété remonte la chaîne de prototypes en s'arrêtant à la première correspondance — c'est pourquoi une définition plus proche surcharge une définition plus éloignée. Inspectez la chaîne avec Object.getPrototypeOf().
  • Dans un constructeur dérivé, appelez super() avant this. Tant que super() ne s'est pas exécuté, l'instance n'est pas initialisée et toute utilisation de this lance une ReferenceError.
  • Accédez explicitement au comportement parent avec super.method() ou super.prop, même si vous l'avez surchargé.
  • Vous pouvez étendre les classes natives comme Array — faites simplement attention au comportement de Symbol.species lorsque les méthodes retournent de nouvelles collections.

Prochaines étapes :

Pratique

Pratique
En ce qui concerne l'héritage de classes JavaScript, quelles affirmations sont vraies ?
En ce qui concerne l'héritage de classes JavaScript, quelles affirmations sont vraies ?
Was this page helpful?