Une classe, c'est un plan pour créer des objets
Une classe javascript décrit la forme et le comportement d'un type d'objet. Tu définis le plan une seule fois, puis tu peux générer autant d'instances que tu veux. Chaque instance possède ses propres données, mais partage les mêmes méthodes.
Voici la structure de base :
class User { ... } définit le plan, et new User(...) en crée une instance. Chaque instance possède ses propres name et email, mais toutes partagent la même méthode greet définie sur la classe.
Deux instances, deux jeux de données, un seul jeu de méthodes. Voilà toute l'idée.
Le constructeur initialise chaque instance
Le constructor est une méthode spéciale qui s'exécute une seule fois par instance, juste au moment où new la crée. Son rôle : initialiser l'objet tout neuf — le plus souvent en recopiant les arguments sur this :
this à l'intérieur du constructeur fait référence à l'instance toute neuve en cours de création. Quand tu écris this.x = x, tu ajoutes x à cet objet précis. Chaque appel à new Point(...) obtient son propre this, donc ses propres x et y.
Si tu ne déclares pas de constructeur, JavaScript t'en fournit un vide automatiquement. Tu n'as besoin d'en écrire un que lorsque tu as vraiment de l'initialisation à faire.
Le mot-clé new : la clé de voûte du mécanisme
Appeler une classe sans new déclenche une erreur :
const p = Point(3, 4);
// TypeError: Class constructor Point cannot be invoked without 'new'
C'est voulu. Le mot clé new fait quatre choses, dans cet ordre :
- Il crée un nouvel objet vide.
- Il le relie au prototype de la classe (là où vivent les méthodes).
- Il exécute le
constructoravecthislié au nouvel objet. - Il retourne le nouvel objet.
Sans new, rien de tout ça ne se produit. La classe impose la règle pour t'éviter de l'oublier par mégarde — un vrai progrès par rapport à l'époque pré-class, où omettre new corrompait silencieusement l'objet global.
Les méthodes sont partagées, les champs sont propres à chaque instance
Les méthodes définies dans le corps de la classe vivent sur le prototype : une seule copie, partagée par toutes les instances. Les champs d'instance (tout ce que tu assignes à this), eux, sont propres à chaque instance — une copie distincte à chaque fois.
Les deux instances ont leur propre count, donc incrémenter l'une n'affecte pas l'autre. En revanche, a.increment et b.increment sont littéralement la même fonction — stockée une seule fois sur le prototype, puis récupérée à chaque appel sur une instance. C'est ce qui rend les classes économiques à l'échelle : mille instances ne créent pas mille copies de chaque méthode.
Les champs de classe
Tu peux déclarer des champs d'instance directement en haut du corps de la classe, en dehors du constructeur :
Les déclarations de champs s'exécutent avant le corps du constructeur, comme si elles étaient écrites tout en haut de constructor. Pratique quand la valeur initiale ne dépend pas des arguments du constructeur — ça évite de surcharger le constructeur avec des this.count = 0; this.step = 1;.
Quand les valeurs dépendent des arguments, on garde l'affectation dans le constructeur, là où les arguments sont accessibles.
Getters et setters en JavaScript
Un getter ou un setter ressemble à une méthode, mais se comporte comme un accès à une propriété. On lit ou on affecte sans parenthèses, et la méthode tourne en coulisses :
Notez les appels : t.fahrenheit (sans parenthèses) déclenche le getter, tandis que t.fahrenheit = 100 appelle le setter. Vu de l'extérieur, fahrenheit ressemble à une propriété tout ce qu'il y a de plus banale, mais sa valeur est en réalité calculée à la volée à partir de celsius.
Les getters sont parfaits pour exposer des valeurs dérivées. Les setters, eux, brillent quand il s'agit de valider ou de normaliser une valeur au moment de l'affectation. Attention toutefois à ne pas en abuser : si un getter fait un travail coûteux, la personne qui lit votre code sera prise au dépourvu de voir qu'un simple « accès à une propriété » déclenche de vrais calculs.
Méthodes raccourcies, noms calculés et this
Dans une classe javascript, les méthodes s'écrivent en syntaxe raccourcie — pas de mot-clé function, pas de : entre le nom et le corps de la méthode :
Renvoyer this depuis add permet le chaînage de méthodes — chaque appel retourne la même instance, ce qui permet d'enchaîner l'appel suivant dessus.
Attention à un piège : les méthodes ne sont pas automatiquement liées à leur instance. Si tu détaches une méthode pour l'appeler toute seule, this est perdu :
Quand on appelle g.hello(), ça marche parce que le . fournit this. Mais fn() tout seul, non. Si tu as besoin d'une méthode détachée déjà liée (cas classique dans les gestionnaires d'événements), tu peux la binder dans le constructeur ou utiliser un champ de classe en fonction fléchée : hello = () => \Hi, ${this.name}`;`.
Un petit exemple concret de classe JavaScript
Mettons tout ça bout à bout — champs, constructeur, méthodes et un getter :
Lisible d'un coup d'œil : la classe décrit précisément ce qu'est un BankAccount et ce qu'il peut faire.
Les classes ne sont que des fonctions, en réalité
Un point à bien intégrer : class n'est, pour l'essentiel, que du sucre syntaxique. En coulisses, une classe JavaScript n'est rien d'autre qu'une fonction — plus précisément une fonction constructeur — et ses méthodes sont stockées sur ClassName.prototype :
typeof User renvoie "function". La méthode greet, elle, vit sur User.prototype. Quand on appelle greet sur une instance, JavaScript la retrouve en remontant la chaîne de prototypes — le même mécanisme qui existe dans le langage depuis ses débuts. Les classes ne font que t'offrir une syntaxe propre pour mettre tout ça en place.
Ce modèle mental te servira plus tard : l'héritage, instanceof et le débogage des chaînes de prototypes deviennent bien plus clairs dès qu'on se rappelle qu'une classe est une fonction avec des méthodes accrochées à son prototype.
La suite : l'héritage
Pour l'instant, chaque classe vit dans son coin. Mais dans la vraie vie, on construit presque toujours des hiérarchies de classes — un Dog qui est une sorte d'Animal, un AdminUser qui est une sorte de User. C'est exactement le rôle des mots-clés extends et super, et on s'y attaque juste après.
Questions fréquentes
Comment déclarer une classe en JavaScript ?
On utilise le mot-clé class suivi d'un nom, puis un bloc contenant une méthode constructor et les autres méthodes. Pour créer une instance, on appelle new NomDeClasse(...). Exemple : class User { constructor(name) { this.name = name; } } puis new User('Ada').
À quoi sert le constructor dans une classe JavaScript ?
Le constructor s'exécute une seule fois, au moment où tu fais new NomDeClasse(...). Son rôle : initialiser la nouvelle instance, généralement en affectant les arguments à this sous forme de propriétés. Si tu n'en écris pas, JavaScript en fournit un par défaut, vide.
Quelle différence entre une classe et une fonction en JavaScript ?
Techniquement, une classe est une fonction — plus précisément une fonction constructeur dont les méthodes sont attachées au prototype. Le mot-clé class est surtout du sucre syntaxique, mais il force l'appel avec new, gère proprement extends et rend les méthodes non énumérables. Pour du code neuf, mieux vaut utiliser class plutôt que d'écrire des fonctions constructeur à la main.