Comprendre le mot clef « this »

Comprendre le mot clef “this”

Deux personnes dans une cuisine séparée, pixel art

J’ai récemment été confronté à l’utilisation du mot clé this dans un cours sur JavaScript sur Udemy.
Le projet consistait à réaliser un jeu de Puissance 4 en programmation orientée objet, ce qui m’a amené à creuser les subtilités de this dans divers contextes. Voici les principaux cas d’usage à connaître :

  • Mode strict vs mode non-strict
  • Contexte global (objet window), objets littéraux, fonctions (fléchées ou classiques), classes
  • Méthodes d’instance .call(), .apply() et .bind()
  • Contexte d’exécution vs environnement lexical
  • Méthodes intégrées (ex. window.addEventListener, setTimeout)

Pour plus de détails, consultez aussi la référence MDN sur this.

Pourquoi revenir sur this en JavaScript ?

Mal compris, this est source de bugs tenaces : erreurs de contexte, références perdues… Qui ne s’est pas arraché les cheveux après une demi-journée de débogage ? 😅

Pour ma part, j’ai frappé un mur en utilisant this dans un écouteur d’événement défini en arrow function : le binding lexical m’a échappé !


1. Contexte global (window)

Dans un script chargé par le navigateur, le contexte global est l’objet window.
Qu’on soit en strict ou non-strict, un simple :

console.log(this === window); // true

confirme que this pointe vers window.
Vous pouvez même invoquer :

console.log(this.document.location);

2. Objets littéraux

Astuce : “Que y a-t-il à gauche du . ?”
this fait référence à l’objet qui précède le point.

const fluffy = {
  name: "Fluffy",
  color: "Rainbow",
  species: "Unicorn",
  sayHi(style, humor) {
    return `${this.name} the ${style} ${this.species} with the ${this.color} color and the ${humor} humor says hi!`;
  }
};

console.log(fluffy.sayHi("pretty", "bright"));
// Fluffy the pretty Unicorn with the Rainbow color and the bright humor says hi!

Mode non-strict vs strict lorsque vous stockez la méthode :

name = "Global";
species = "GlobalSpecies";
color = "GlobalColor";

const fluffySayHi = fluffy.sayHi;

console.log(fluffySayHi("pretty", "bright"));
// non-strict : 'Global the GlobalSpecies with the GlobalColor color says hi!'
// strict : undefined...

3. .call(), .apply(), .bind()

.call()

fluffySayHi.call(fluffy, "pretty", "bright");

.apply()

fluffySayHi.apply(fluffy, ["pretty", "bright"]);

.bind()

const bound = fluffy.sayHi.bind(fluffy);
console.log(bound("pretty", "bright"));

4. Fonctions fléchées vs classiques

  • Fléchées héritent du this lexical :

    function Unicorn(name) {
      this.name = name;
      this.getName = () => console.log(this.name);
    }
    const u = new Unicorn("Fluffy");
    setTimeout(u.getName, 0); // 'Fluffy'
    
  • Classiques créent leur propre this selon l’appel :

    function Unicorn(name) {
      this.name = name;
      this.getName = function() { console.log(this.name); };
    }
    const u2 = new Unicorn("Fluffy");
    setTimeout(u2.getName, 0); // undefined
    

5. new, classes ES6 et super

En ES6, le constructeur et les méthodes de classe utilisent this pour l’instance :

class Unicorn {
  constructor(name) { this.name = name; }
  getName() { return this.name; }
}

Les arrow methods dans une classe héritent aussi du this lexical de l’instance.


6. Méthodes globales (addEventListener, setTimeout)

  • addEventListener : this = l’élément cible
  • setTimeout classique : this = window (ou undefined en strict)
  • Remède : arrow function ou .bind(this) dans le callback

Gardez toujours en tête que la valeur de this dépend du contexte d’exécution et de l’environnement lexical. ☕🦄

Ressources




Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • Comprendre l’utilisation du module next-image avec Storybook & TypeScript
  • Comprendre l'asynchrone en JavaScript