JavaScript : Qu'est ce que this ? Que vaut this ?
#1
Qu'est-ce que this ?
this
est un opérateur et comme tout opérateur, il retourne une valeur.
- D'où vient cette valeur ? Cette valeur provient d'un contexte d'exécution. Il faut savoir qu'au lancement du script, et ensuite à chaque appel d'une fonction, un contexte d'exécution est placé en pile d'exécution.
- Qu'y a-t-il dans un contexte d'exécution ? Il y a la valeur de
this
ça je viens de le dire et il y a aussi des informations qui vont permettre à la fonction de s'exécuter, par exemple les arguments qui lui sont passés. Je ne détaille pas plus. Mais vous pouvez déjà comprendre qu'à chaque appel d'une fonction, étant donné que l'on change les arguments, eh bien, on va créer un nouveau contexte. Ce qu'il faut retenir ici, c'est l'idée, car en fait, il y a beaucoup plus d'informations que ça dans un contexte d'exécution. - Qui gère cette valeur de
this
? Qui l'affecte ? Eh bien, c'est le moteur JavaScript qui le fait et qui le fait pour nous. - Alors c'est gentil, mais à quoi ça va me servir ? Par exemple quand vous instanciez une classe pour créer un nouvel objet et bien dans la fonction constructeur
this
va désigner ce nouvel objet. Autre exemple : quand vous passez un callback à un gestionnaire d'événement et bien dans ce callbackthis
va désigner l'élément du document sur lequel est posé ce gestionnaire. - Et si la valeur de
this
ne vous convient pas ? il faut que vous sachiez que vous pouvez la changer en utilisant les méthodescall
,apply
oubind
du constructeurFunction
. On voit ça dans un autre tuto. - Que vaut
this
? Pour pouvoir utiliser la valeur dethis
, vous devez être capable de prévoir ce que va faire le moteur JavaScript et pour cela, on va étudier dans ce tuto les situations les plus courantes dans lesquelles des fonctions vont être invoquées. Il faut aussi savoir que la valeur dethis
peut dépendre :- dans un très petit nombre de cas, de l'utilisation ou pas, du mode strict.
- de l'environnement d'exécution de JavaScript, à savoir le navigateur ou un serveur.
Une précision au niveau du vocabulaire que j'utilise dans ce tuto : un objet étant l'instance d'une classe, j'utilise indifféremment les mots objet ou instance.
#2
This avec une fonction classique invoquée dans la portée globale
On va commencer par un cas simple, celui d'une fonction déclarée et invoquée dans la portée globale. On va demander à cette fonction de nous retourner sa valeur de this
.
Au préalable, une petite précision : Peu importe la manière dont la fonction est déclarée. Elle peut être déclarée comme une fonction classique ou comme une expression ou être une fonction auto invoquée. Cela ne change rien à la valeur de this
.
Faisons un test avec une fonction qui nous retourne la valeur de this
.

On constate que le console.log
affiche la valeur de l'objet global window
. Il se trouve que window
appartient à l'environnement "navigateur" du moteur JavaScript. Dans ces conditions, il est logique de se poser une question : Que donnera ce code si je l'exécute sous node.js
, puisque sous node.js
, nous avons un environnement "serveur" et que window
n'existe pas ?
On fait un test et là, on constate qu'on obtient aussi une valeur globale, mais qui cette fois-ci vaut Object [global]
. Voir ci-dessous le résultat d'une exécution sous Node.js
depuis VS Code
.

Maintenant, on continue nos tests en exécutant les mêmes codes, mais cette fois-ci en mode strict. Et dans ce cas, des deux côtés, this
prend la valeur undefined
.

Au-dessus, on vient de voir les cas où la valeur de this
dépend soit de l'environnement, soit de l'utilisation ou pas du mode strict. Maintenant, on va passer à des cas qui sont indépendants de ces deux situations.
#3
This dans le callback d'un gestionnaire d'événement
Dans un gestionnaire d'événement, quand un callback passé en argument est invoqué, this
pointe sur l'élément sur lequel le gestionnaire est posé.
Dans l'exemple ci-dessous, je place un élément HTML button
pour créer un bouton. Et ensuite, je clique sur ce bouton.
Une petite remarque sur ce que l'on voit pour ne pas tout mélanger. Le console.log(this)
vous affiche le code HTML du bouton. Mais si on veut être précis, this
ici est une référence puisque le typeof this
retourne object
. Donc en réalité this
pointe sur l'objet JavaScript qui correspond à cet élément HTML dans l'arbre DOM.

#4
This sur un new
On va regarder ce qui se passe sur un new
. Je précise que c'est la même chose de faire un new
sur une fonction constructeur ou sur une classe. Le this
ici pointe sur un objet vide. Cet objet est une instance de la classe Obj
. Alors, je ne le fais pas dans cet exemple, mais en situation courante, on se sert de cette valeur de this
pour ajouter des propriétés à l'objet de manière à le construire.
this
afin de voir apparaître sa valeur qui est ici égale à un objet vide.
#5
This avec une méthode d'un objet
Dans l'exemple ci-dessous, je déclare une classe, je déclare sa fonction constructeur, je lui ajoute une propriété click
qui est un booléen que j'initialise à la valeur false
. Je crée la méthode set
qui servira à placer la valeur de click
à true
. Ensuite, je crée un objet en instanciant la classe. Le but du truc, c'est de mémoriser le fait qu'il y a eu un click
. Ensuite, j'appelle la méthode obj.set
et je regarde la valeur de this
. Dans ce cas, this
vaut obj
qui pointe sur l'instance qui vient d'être créée.

Maintenant, je vais récupérer mon bouton avec son gestionnaire d'événement. Mon but, c'est toujours le même, à savoir, mémoriser le clic sur le bouton dans obj
.
Pour ça, je vais mettre la méthode obj.set
de l'objet comme callback du gestionnaire. Mais qu'est-ce qui va se passer, au moment de l'invocation du callback dans le gestionnaire ? La méthode set
de obj
trouve un this
qui à la valeur but
. C'est cette valeur qu'elle va utiliser, si bien que c'est avec but
que va être exécuté le this.click=true
et pas avec obj
. En fait, on va faire en quelque sorte un but.click = true
à la place d'un obj.click = true
car dans ce cas et pour notre besoin la valeur de this
n'est pas la bonne.

Dans ces situations, le debugger peut nous aider, car il nous permet de voir ce que désigne this
facilement. Il suffit de mettre un point d'arrêt dans la méthode set
.
Pour cela, je vais dans Sources
et je clique sur la ligne où je veux placer le point d'arrêt. Ici, je le place sur le this.click = true
. Puis, je clique sur le bouton. Le debugger va s'arrêter sur le point d'arrêt sans exécuter l'instruction. Je peux voir dans la zone Scope que this
désigne button
. Je peux voir dans la console, que le console.log(this)
, affiche l'élément HTML button
.

Attention, cela ne veut pas dire que this
est égal à button
. Le debugger vous dit this
deux points button
et button
, c'est une valeur qui appartient au HTML.
Je vais vous faire un schéma pour que vous compreniez bien les informations qui vous sont données. Nous avons this
qui est égal à but
. Donc but
et this
pointent tous les deux sur un même objet de l'arbre DOM. Un objet de constructeur HTMLButtonElement
et qui correspond à l'élément HTML button
.
Le debugger vous donne l'information utile. Le schéma vous détaille la chaîne.

Ce problème peut être facilement résolu, en appliquant la méthode bind
au callback qui est passé au gestionnaire. Je détaille tout ça dans un autre tuto dans lequel je fais les méthodes call
, apply
, et bind
du constructeur Function
, dont le but est la maîtrise de la valeur de this
.
#6
This avec une fonction fléchée
Maintenant, dans la déclaration de notre classe, on modifie la méthode set
et on remplace par une fonction fléchée.
On constate que le this
reste pointé sur l'objet obj
ce qui est logique, car une fonction fléchée hérite du this
de la portée englobante à l'endroit de sa déclaration. Ici, dans l'objet, this
pointe sur l'instance obj
. La fonction fléchée est déclarée dans l'instance donc elle hérite de ce this
et au moment de l'invocation, elle se le garde.
Vous pouvez constater ci-dessous, que la valeur a été mémorisée dans l'objet obj
, bien que la méthode ait été invoquée dans le gestionnaire.
