
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'est qu'il y a 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 et 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 ? Et 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 les 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 et aussi 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.
