Comprenez la résolution dynamique de this, la chaîne de prototypes et ce que les classes ajoutent réellement au modèle objet.
Ouvrir cette leçon dans KodokonLa valeur de this se décide au site d'appel, pas à la déclaration. Quatre règles, par priorité décroissante : appel avec new, liaison explicite (call, apply, bind), appel comme méthode (obj.fn()), et appel libre (fn()), qui donne undefined en mode strict. Le bug le plus fréquent du métier en découle : extraire une méthode de son objet casse la liaison implicite.
const user = {
name: "Ada",
greet() {
return "Bonjour, " + this.name;
},
};
console.log(user.greet()); // "Bonjour, Ada"
const detached = user.greet;
// detached(); // TypeError : this vaut undefined
const bound = user.greet.bind(user);
console.log(bound()); // "Bonjour, Ada"Les fonctions fléchées ne possèdent pas de this : elles capturent lexicalement celui de la portée englobante, comme une closure. C'est idéal pour les callbacks, mais contre-productif pour les méthodes d'objet littéral, où this pointera vers la portée extérieure. Sous le capot, tout objet délègue via sa chaîne de prototypes : une propriété absente est cherchée de maillon en maillon jusqu'à null.
function Animal(name) {
this.name = name;
}
Animal.prototype.describe = function () {
return this.name + " est un animal";
};
const dog = new Animal("Rex");
console.log(dog.describe()); // "Rex est un animal"
console.log(Object.getPrototypeOf(dog) ===
Animal.prototype); // true
console.log(dog.hasOwnProperty("describe")); // falseLa syntaxe class ne change pas ce modèle : elle le rend lisible. Les méthodes déclarées dans le corps de la classe atterrissent sur Constructor.prototype et sont donc partagées. Les champs d'instance (dont les fléchées assignées comme champs) sont recréés par instance : liaison de this garantie, mais coût mémoire multiplié. Les champs #privés offrent enfin une confidentialité vérifiée par le moteur, contrairement à la convention _underscore.
class BankAccount {
#balance = 0;
deposit(amount) {
if (amount <= 0) throw new Error("Montant invalide");
this.#balance += amount;
return this;
}
get balance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(50).deposit(25);
console.log(account.balance); // 75this lors d'un appel libre fn() sans objet ni liaison explicite ?this ?