Avez-vous une question? (216) 97 656 803 hajjriadh@gmail.com
JavaScript

Le mot-clé this en JavaScript

Le mot-clé this en JavaScript. Dans cette leçon du cours JavaScript, vous apprendrez à : comprendre que this dépend de la façon dont la fonction est appelée ; reconnaître la perte de this quand une mé...

0 chapitres 0 QCM Accès gratuit
Dans cet article

À propos de ce cours

Le mot-clé this en JavaScript. Dans cette leçon du cours JavaScript, vous apprendrez à : comprendre que this dépend de la façon dont la fonction est appelée ; reconnaître la perte de this quand une méthode est passée en callback ; utiliser les fonctions fléchées et bind pour conserver this ; connaître call, apply et bind.

Chapitre 16 — La programmation orientée objet · 16.2 Le mot-clé this en JavaScript

🎯 Objectifs de la leçon
• comprendre que this dépend de la façon dont la fonction est appelée ;
• reconnaître la perte de this quand une méthode est passée en callback ;
• utiliser les fonctions fléchées et bind pour conserver this;
• connaître call, apply et bind.

1. this désigne l'objet qui appelle

Dans une méthode, this désigne l'objet sur lequel la méthode a été appelée : ce qui est écrit avant le point. Il n'est pas fixé quand on écrit la méthode, mais au moment de l'appel.

class Minuteur {
  constructor(nom) {
    this.nom = nom;
  }
  presenter() {
    return `Je suis ${this.nom}`;
  }
}

const m = new Minuteur("Chrono");
console.log(m.presenter()); // this = m (l'objet avant le point)

const presenterSeule = m.presenter; // on détache la méthode de son objet
try {
  presenterSeule(); // plus d'objet avant le point → this = undefined
} catch (e) {
  console.log(e.constructor.name + " :", e.message);
}

Résultat dans la console

Je suis Chrono
TypeError : Cannot read properties of undefined (reading 'nom')

En détachant la méthode, on perd « l'objet avant le point ». Dans une classe (toujours en mode strict), this vaut alors undefined.

Valeur de this selon la façon d'appeler une fonction
Figure 1 — Les cinq règles de this.

2. Le piège des callbacks

Passer une méthode à setTimeout, addEventListener ou forEach revient à la détacher de son objet :

class Compteur {
  constructor() {
    this.valeur = 0;
  }
  incrementer() {
    this.valeur++;
    console.log("valeur =", this.valeur);
  }
}

const c = new Compteur();

// ✗ La méthode est passée SEULE : setTimeout l'appelle sans notre objet,
//   this n'est plus c → this.valeur n'existe pas → undefined + 1 = NaN
setTimeout(c.incrementer, 0);

// ✓ Solution 1 : une fonction fléchée qui appelle la méthode SUR l'objet
setTimeout(() => c.incrementer(), 10);

// ✓ Solution 2 : bind crée une copie de la fonction avec this fixé
setTimeout(c.incrementer.bind(c), 20);

Résultat dans la console

valeur = NaN
valeur = 1
valeur = 2

Le premier appel affiche NaN: this n'était plus le compteur, donc this.valeur était undefined. Deux solutions :

  • une fonction fléchée qui appelle la méthode sur l'objet : () => c.incrementer();
  • bind, qui crée une copie de la fonction avec this fixé : c.incrementer.bind(c).

3. Les fonctions fléchées n'ont pas leur propre this

Une fonction fléchée reprend le this du code qui l'entoure. C'est idéal à l'intérieur d'une méthode, mais pas comme méthode d'un objet littéral :

class Horloge {
  constructor() {
    this.secondes = 0;
  }
  demarrer() {
    // La fonction fléchée n'a PAS son propre this : elle prend celui de demarrer()
    const id = setInterval(() => {
      this.secondes++;
      console.log("tic", this.secondes);
      if (this.secondes === 3) clearInterval(id);
    }, 100);
  }
}
new Horloge().demarrer();

// ✗ À l'inverse, une fléchée comme méthode d'objet littéral n'a pas l'objet comme this
const chat = {
  nom: "Minou",
  direNomFleche: () => `this.nom = ${this.nom}`, // this ne désigne PAS chat
  direNom() { return `this.nom = ${this.nom}`; },
};
console.log("Fléchée :", chat.direNomFleche());
console.log("Méthode :", chat.direNom());

Résultat dans la console

Fléchée : this.nom = undefined
Méthode : this.nom = Minou
tic 1
tic 2
tic 3

4. call, apply et bind

function presenter(salutation, ponctuation) {
  return `${salutation}, je suis ${this.nom}${ponctuation}`;
}
const amina = { nom: "Amina" };

console.log(presenter.call(amina, "Bonjour", " !"));    // arguments un par un
console.log(presenter.apply(amina, ["Salut", "."]));    // arguments dans un tableau
const presenterAmina = presenter.bind(amina, "Coucou"); // nouvelle fonction, this fixé
console.log(presenterAmina(" :)"));

Résultat dans la console

Bonjour, je suis Amina !
Salut, je suis Amina.
Coucou, je suis Amina :)
// Dans une page web : le piège classique avec addEventListener
class Bouton {
  constructor(element) {
    this.clics = 0;
    // ✗ element.addEventListener("click", this.compter);  → this = l'élément HTML
    element.addEventListener("click", () => this.compter()); // ✓
  }
  compter() {
    this.clics++;
  }
}
ℹ️ À retenir
• this = l'objet avant le point, au moment de l'appel.
• Une méthode passée seule en callback perd son objet : this devient undefined (ou autre chose).
• Une fonction fléchée n'a pas son propre this: elle garde celui du code qui l'entoure.
• bind(obj) fixe this définitivement ; call et apply appellent avec un this choisi.

🛠 Activité 2 — Chasser les bugs de this

Mission : Chaque question contient un bug lié à this. Prédisez le résultat, testez, puis corrigez.

Questions pour avancer (répondez dans votre compte rendu, puis appliquez dans votre projet) :

  1. Que se passe-t-il et pourquoi ?
    class Chrono {
      constructor() { this.s = 0; }
      tic() { this.s++; console.log(this.s); }
      lancer() { setInterval(this.tic, 1000); }
    }
    new Chrono().lancer();
    Proposez deux corrections différentes.
  2. Pourquoi afficherTous plante-t-elle ?
    class Classe {
      constructor(nom, eleves) { this.nom = nom; this.eleves = eleves; }
      afficherTous() {
        this.eleves.forEach(function (e) { console.log(this.nom, e); });
      }
    }
    Corrigez-la avec une fonction fléchée.
  3. Créez une page avec un bouton et une classe CompteurClics. Utilisez d'abord addEventListener("click", this.compter) et affichez this dans compter: que contient-il ? Corrigez.
  4. Pourquoi ne faut-il pas écrire les méthodes d'une classe sous forme de fonctions fléchées partagées ? (indice : écrivez compter = () => { … } dans la classe, puis comparez a.compter === b.compter pour deux instances)
  5. Avec call, empruntez la méthode presenter de votre classe Etudiant (activité 1) pour l'appliquer à un simple objet { nom: "Invité", notes: [] }. Que se passe-t-il ?

Je vérifie / je rends :

  • ☐ Les codes corrigés et, pour chacun, une phrase qui explique la cause du bug.

← 16.1 La programmation orientée objet : classes et instances16.3 Getters, setters et membres statiques →