W3docs

Prototypes natifs de JavaScript

Découvrez les prototypes natifs de JavaScript : Object.prototype, Array, Function et Number, l'emprunt de méthodes avec call et apply, et pourquoi étendre les prototypes natifs est déconseillé.

Explorer les prototypes natifs

Les prototypes natifs en JavaScript sont les objets que les constructeurs intégrés tels que Array, Object, String, Number et Function utilisent pour partager des méthodes et des propriétés avec chaque valeur qu'ils créent. Lorsque vous appelez [1, 2, 3].map(...) ou "hi".toUpperCase(), la méthode appelée ne réside pas sur le tableau ou la chaîne elle-même — elle réside sur Array.prototype ou String.prototype et est trouvée en parcourant la chaîne de prototypes.

Cette page explique où ces prototypes se situent dans la chaîne, comment les inspecter, comment emprunter leurs méthodes pour des objets qui ne sont pas de vrais tableaux, et pourquoi les étendre de manière permanente est déconseillé. Si vous débutez avec le fonctionnement de la chaîne elle-même, lisez d'abord l'héritage prototypal.

Le rôle des prototypes natifs

Les prototypes natifs sont au cœur de JavaScript : c'est grâce à eux que chaque valeur littérale dispose de méthodes utiles sans que vous ayez à définir quoi que ce soit. Comprendre comment ils s'insèrent dans la chaîne de prototypes vous permet de déchiffrer les messages d'erreur, de réutiliser les méthodes intégrées dans des contextes inattendus, et d'éviter des bugs subtils.

Object.prototype : la racine de la chaîne

Presque tout object que vous créez hérite finalement de Object.prototype, qui se trouve au sommet de la chaîne. C'est de là que proviennent des méthodes comme toString, hasOwnProperty et valueOf. Lorsqu'une recherche échoue sur un object et sur chaque prototype intermédiaire, la chaîne se termine à Object.prototype, et le maillon suivant est null.

javascript— editable

Les prototypes Array, Function et Number

Les types intégrés superposent leur propre prototype au-dessus de Object.prototype. Un tableau, par exemple, hérite de Array.prototype (qui fournit map, filter, push, …), et Array.prototype hérite à son tour de Object.prototype. Le même schéma s'applique aux fonctions et aux nombres.

javascript— editable

Emprunter des méthodes avec call et apply

Étant donné que les méthodes natives résident sur des prototypes, vous pouvez les emprunter et les exécuter sur n'importe quelle valeur compatible en utilisant call ou apply. L'exemple classique consiste à utiliser les méthodes de Array.prototype sur des objets semblables à des tableaux (comme arguments ou une string) qui ne possèdent pas ces méthodes en propre.

javascript— editable

Étendre les prototypes natifs

Bien que JavaScript permette d'étendre les prototypes natifs, cette pratique est généralement déconseillée dans la portée globale en raison de conflits potentiels dans des bases de code plus larges ou avec des scripts tiers. Il existe plusieurs raisons concrètes de l'éviter :

  • Collisions de noms. Si deux scripts ajoutent une méthode portant le même nom (ou si une future version d'ECMAScript standardise ce nom avec un comportement différent), l'un écrase silencieusement l'autre.
  • Énumérabilité. Une méthode ajoutée par simple assignation est énumérable, et apparaît donc dans les boucles for...in sur chaque object de ce type, à moins d'être protégée par hasOwnProperty — une source courante de bugs.
  • Effets de bord globaux. Le changement affecte chaque valeur de ce type dans tout le programme, y compris le code que vous n'avez pas écrit.

L'extrait ci-dessous illustre le piège de for...in. Une assignation classique se retrouve dans la boucle ; l'utilisation de Object.defineProperty pour rendre la méthode non énumérable permet de l'éviter.

javascript— editable

Comprendre cette capacité reste utile pour identifier des problèmes potentiels, lire des polyfills et explorer des patterns avancés dans des environnements contrôlés.

Exemples pratiques avec les prototypes natifs

Manipuler des tableaux avec Array.prototype

Considérez la puissance de Array.prototype qui offre des méthodes comme map, filter et reduce. Ces méthodes fournissent des solutions élégantes pour transformer et traiter les données stockées dans des tableaux. Nous pouvons ajouter de nouvelles méthodes en manipulant Array.prototype.


javascript— editable

Dans cet exemple, nous définissons une nouvelle méthode mapToSquare sur le prototype, qui utilise la méthode intégrée map pour retourner le carré de chaque nombre.

Enrichir les chaînes avec String.prototype

String.prototype est également un riche répertoire de méthodes, telles que toLowerCase, toUpperCase et includes, qui facilitent la manipulation et l'interrogation des chaînes de caractères.


javascript— editable

Dans cet exemple, nous définissons removeSpace sur le prototype, en utilisant split, filter et join pour supprimer les espaces.

Extensions personnalisées des prototypes natifs

Bien que la prudence soit de mise, l'ajout de méthodes personnalisées aux prototypes natifs peut illustrer la flexibilité de JavaScript. Voici comment vous pourriez étendre Array.prototype pour inclure une méthode calculant la somme des éléments d'un tableau :


javascript— editable

Cette méthode personnalisée, sum, ajoute une nouvelle dimension au prototype Array, illustrant à la fois le potentiel et les risques de l'extension des prototypes natifs.

Bonnes pratiques pour l'utilisation des prototypes natifs

Bien que la puissance des prototypes natifs soit indéniable, voici quelques bonnes pratiques pour que votre code reste robuste et sans conflits :

  • Évitez d'étendre les prototypes natifs : sauf absolue nécessité, évitez de modifier les prototypes intégrés pour prévenir des comportements inattendus dans votre code ou dans des bibliothèques tierces.
  • Utilisez Object.defineProperty pour des extensions plus sûres : lorsque vous devez ajouter des méthodes, utilisez Object.defineProperty pour les rendre non énumérables. Cela empêche les boucles for...in de récupérer vos propriétés personnalisées et réduit les conflits de noms.
  • Utilisez les polyfills avec discernement : lorsque vous utilisez des polyfills pour combler des fonctionnalités manquantes dans les navigateurs plus anciens, assurez-vous qu'ils vérifient l'existence de la méthode avant de l'ajouter au prototype.
  • Tirez parti des fonctionnalités modernes de JavaScript : avec l'évolution de JavaScript, de nombreuses tâches qui nécessitaient autrefois d'étendre les prototypes natifs peuvent désormais être réalisées avec de nouvelles constructions du langage, telles que les classes et les modules.

Conclusion

Les prototypes natifs sont le mécanisme derrière chaque méthode intégrée que vous utilisez quotidiennement : ils s'inscrivent dans la chaîne de prototypes, avec Object.prototype à la racine, et permettent aux valeurs comme les tableaux, les fonctions et les nombres de partager des comportements. Savoir les inspecter avec Object.getPrototypeOf, emprunter leurs méthodes avec call et apply, et résister à l'envie de les étendre globalement rendra votre code à la fois plus capable et plus prévisible.

Pour aller plus loin, consultez l'héritage prototypal pour comprendre comment la chaîne est construite, et les méthodes de prototype et les objets sans __proto__ pour l'API moderne Object.create / Object.getPrototypeOf.

Pratique

Pratique
Qu'est-ce qui est vrai concernant l'extension des prototypes natifs en JavaScript ?
Qu'est-ce qui est vrai concernant l'extension des prototypes natifs en JavaScript ?
Was this page helpful?