Apprends la syntaxe des classes ES6 pour créer des objets, utiliser les constructeurs, méthodes, getters/setters, membres statiques, et l'héritage avec extends.
ES6 a introduit le mot-clé class comme une syntaxe plus claire pour créer des objets avec un comportement partagé. Une classe est essentiellement un plan pour créer des objets.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old.`;
}
}
const alice = new Person('Alice', 30);
console.log(alice.greet()); // "Hi, I'm Alice and I'm 30 years old."Éléments clés :
constructor — une méthode spéciale appelée automatiquement lorsque tu crées une instance avec new. Elle initialise les propriétés de l'objet.greet()).new — crée une nouvelle instance de la classe.Les classes sont du sucre syntaxique par-dessus l'héritage prototypal existant de JavaScript. En coulisses, class Person crée toujours une fonction constructeur et ajoute des méthodes à Person.prototype. Mais la syntaxe des classes est beaucoup plus lisible.
Contrairement aux déclarations de fonction, les déclarations de classe ne sont PAS remontées :
const p = new Person('Alice', 30); // ReferenceError!
class Person { ... }Tu dois définir la classe avant de l'utiliser. C'est voulu — cela prévient les bugs subtils causés par la remontée.
Les getters et setters te permettent de définir des propriétés calculées et d'ajouter une validation lors de l'assignation de valeurs. Ils ressemblent à des méthodes mais sont accessibles comme des propriétés (sans parenthèses).
class Circle {
constructor(radius) {
this.radius = radius;
}
// Getter — propriété calculée
get area() {
return Math.PI * this.radius ** 2;
}
get diameter() {
return this.radius * 2;
}
// Setter — validation lors de l'assignation
set radius(value) {
if (value < 0) {
throw new RangeError('Radius cannot be negative');
}
this._radius = value;
}
get radius() {
return this._radius;
}
}
const c = new Circle(5);
console.log(c.area); // 78.539... (pas de parenthèses !)
console.log(c.diameter); // 10
c.radius = 10; // utilise le setter
// c.radius = -1; // lance RangeErrorES2022 a introduit les champs privés avec le préfixe #. Les champs privés sont vraiment inaccessibles depuis l'extérieur de la classe :
class BankAccount {
#balance = 0; // champ privé
deposit(amount) {
this.#balance += amount;
}
get balance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(100);
console.log(account.balance); // 100
// console.log(account.#balance); // SyntaxError!Les méthodes et propriétés statiques appartiennent à la classe elle-même, pas aux instances. Elles sont appelées sur la classe, pas sur les objets créés à partir de celle-ci.
class MathUtils {
static PI = 3.14159;
static square(n) {
return n * n;
}
static cube(n) {
return n * n * n;
}
}
console.log(MathUtils.PI); // 3.14159
console.log(MathUtils.square(4)); // 16
console.log(MathUtils.cube(3)); // 27
// Ne peut pas être appelé sur les instances :
const m = new MathUtils();
// m.square(4); // TypeError: m.square is not a functionLes méthodes statiques sont couramment utilisées pour :
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
static createAdmin(name) {
return new User(name, 'admin');
}
static createGuest() {
return new User('Guest', 'guest');
}
}
const admin = User.createAdmin('Alice');
const guest = User.createGuest();Tu as déjà utilisé des méthodes statiques intégrées : Array.isArray(), Object.keys(), Date.now(), JSON.parse(). Elles appartiennent toutes à la classe, pas aux instances.
Le mot-clé extends crée une classe enfant qui hérite de toutes les propriétés et méthodes d'une classe parente :
class Animal {
constructor(name, sound) {
this.name = name;
this.sound = sound;
}
speak() {
return `${this.name} says ${this.sound}!`;
}
}
class Dog extends Animal {
constructor(name) {
super(name, 'Woof'); // appelle le constructeur parent
this.tricks = [];
}
learn(trick) {
this.tricks.push(trick);
}
showTricks() {
return `${this.name} knows: ${this.tricks.join(', ')}`;
}
}
const rex = new Dog('Rex');
console.log(rex.speak()); // 'Rex says Woof!' (hérité)
rex.learn('sit');
rex.learn('shake');
console.log(rex.showTricks()); // 'Rex knows: sit, shake'Règles clés pour l'héritage :
super() doit être appelé dans le constructeur enfant avant d'utiliser this. Il appelle le constructeur du parent.super.method() pour appeler la version parente d'une méthode surchargée :
class Cat extends Animal {
speak() {
return super.speak() + ' (purrs)';
}
}instanceof vérifie la chaîne d'héritage :
console.log(rex instanceof Dog); // true
console.log(rex instanceof Animal); // trueL'héritage crée une relation "est-un". Un Dog est un Animal. Utilise-le quand il y a une hiérarchie claire, mais préfère la composition (objets contenant d'autres objets) quand la relation est "a-un".
<div id="output"></div>
<script>
class Animal {
constructor(name, sound) {
this.name = name;
this.sound = sound;
}
speak() {
return `${this.name} says ${this.sound}!`;
}
}
class Dog extends Animal {
constructor(name) {
super(name, 'Woof');
this.tricks = [];
}
learn(trick) {
this.tricks.push(trick);
}
describe() {
const base = this.speak();
const tricks = this.tricks.length
? ` Knows: ${this.tricks.join(', ')}`
: ' No tricks yet.';
return base + tricks;
}
}
const dog = new Dog('Buddy');
dog.learn('sit');
dog.learn('roll over');
const cat = new Animal('Whiskers', 'Meow');
const output = document.getElementById('output');
output.innerHTML = `
<p>${dog.describe()}</p>
<p>${cat.speak()}</p>
<p>Is Dog an Animal? ${dog instanceof Animal}</p>
`;
</script>Que dois-tu appeler dans le constructeur d'une classe enfant avant d'utiliser `this` ?