opérateur this

Javascript : l’opérateur this

Temps de lecture : 7 min

Pour le premier article de cette nouvelle année, nous allons nous intéresser au fonctionnement de l’opérateur this en JavaScript. Bien qu’il puisse paraître simple au premier abord, celui-ci se révèle bien plus complexe qu’il en a l’air notamment pour les développeurs venant d’autres langages.

Une histoire de contexte…

Dans la plupart des langages de programmation orientés objet tels que PHP , Java ou encore C++, this fait référence à l’instance actuelle d’une classe. En JavaScript, il ne désigne pas nécessairement l’objet courant, mais dépend plutôt du contexte dans lequel il est utilisé, ce qui est souvent source d’erreur et d’incompréhension. Faisons un peu le tour des différents types de contextes.

Le contexte global

Lorsque this est appelé en dehors de toute fonction, l’objet sur lequel celui-ci pointe est différent suivant l’environnement d’exécution.

Le navigateur web

Dans le cas d’une exécution dans le navigateur web, this fait référence à l’objet global window :

Node.js

Bien que Node.js possède un objet global nommé global , this ne fait pas référence à celui-ci. Node.js utilise le principe de module, le code que vous écrivez sera donc exécuté à l’intérieur d’un module. De ce fait, this fait référence à l’objet exports (ou module.exports qui est le même objet) :

Pour faire simple, lors de la création d’un module, Node.js encapsule votre code dans une fonction afin de ne pas polluer l’espace global (l’objet global ) et y injecte l’objet exports comme valeur pourthis. Pour les plus téméraires d’entre vous, je vous invite à allez voir directement le code source de Node.js concernant les modules : module.js

Le contexte d’une fonction

JavaScript utilise en interne un mécanisme appelé “référence”. Ce mécanisme permet la résolution d’identifiant ou de propriété d’objet. Il utilise trois propriétés qui sont :

  • base : Cette propriété peut prendre plusieurs valeurs :
    • L’objet qui fait appel à un accesseur de propriété (pour faire simple, ce qui se trouve à gauche du ” .” ou ” []” );
    • L’objet global dans le cas contraire.
  • name : Représente l’identifiant ou le nom de la propriété de l’objet;
  • strict : Indique simplement si le mode strict est activé ou non.

Ainsi dans le cas d’un appel d’une fonction, une référence est créée et permet à JavaScript de connaitre le nom de la fonction à appeler, il s’agit de la propriété name de la référence, mais également la valeur de this à l’intérieur de cette fonction puisqu’il s’agit simplement de la propriété base. Pour vraiment simplifier, vous pouvez imaginer que JavaScript remplace en interne, votre appel de fonction par :

Vous êtes surement déjà tombé sur l’erreur ReferenceError lors de l’appel à une fonction qui n’existe pas :

C’est tout simplement que la référence créée ne permet pas la résolution de l’identifiant notExistsFunction.

Par souci de simplicité et de clarté, nous représenterons, dans la suite de l’article, la référence sous la forme d’un objet littéral :

Voyons maintenant les différents cas d’appels de fonctions.

Les fonctions “ordinaires”

Prenons le cas d’une fonction “ordinaire” :

Lorsque nous appelons la fonction test, une “référence” est créée. Notre objet Reference ressemble donc à ceci :

La propriété name a donc pour valeur test. Le mode strict n’étant pas activé, la propriété strict a pour valeur false . Comme nous ne faisons pas appel à un accesseur de propriété lors de l’appel à la fonction test, la propriété base a pour valeur l’objet global qui dépend de l’environnement d’exécution.

Le navigateur web

Dans le cas d’une exécution dans le navigateur web, voici à quoi ressemble notre objet Reference :

La propriété base a donc pour valeur l’objet global window , de ce fait this fait référence à window :

Node.js

Dans le cas de Node.js, voici à quoi ressemble notre objet Reference :

la propriété base a donc pour valeur l’objet global global , de ce fait this fait également référence à global :

Mode strict

Lors de l’utilisation du mode strict, this est égal à undefined afin de prévenir tout risque de modification de l’objet global :

Les méthodes d’un objet

Lorsque nous appelons une méthode d’un objet, nous faisons appelle à un accesseur de propriété :

Ainsi lors de l’appel à la méthode test, une “référence” est créée et notre objet Reference ressemble à ceci :

Comme je l’ai dit précédemment, la propriété base et donc this, a pour valeur l’objet qui fait appel à un accesseur de propriété. Dans cet exemple, l’objet obj utilise l’accesseur de propriété “.“, this dans la fonction test, fait donc référence à cet objet. Par contre dans l’exemple suivant, this ne fait pas référence à l’objet obj, mais à l’objet global  :

On aurait pu s’attendre à ce que this fasse référence à l’objet obj, mais lors de l’affectation de la méthode test à la variable unbindTest, nous “brisons” le lien avec l’objet obj car nous ne faisons pas appel à un accesseur de propriété lors de l’appel à la fonction unbindTest. S’il y a une chose à retenir c’est que this fait référence à ce qui se trouve à gauche d’un accesseur de propriété que ce soit la notation point “.” ou crochets “[]“.

Le constructeur

La valeur de this, dans le cas d’un constructeur est très simple. Il correspond à l’instance de l’objet qui vient d’être créé lors de l’appel à l’opérateur new. Nous avons vu dans l’article sur l’héritage multiple comment fonctionnait cet opérateur. Pour rappel lors de l’appel à l’opérateur new :

  • Un nouvel objet est créé à partir de l’objet prototype du constructeur;
  • Le constructeur est appelé en lui fournissant comme valeur this l’objet nouvellement créé;
  • L’objet est retourné.

L’implémentation naïve de l’opérateur new donnerait ceci :

Je reviendrais plus en détail sur la fonction apply dans la suite de cet article.

Les fonctions fléchées

Nous avons vu que chaque fonction possède son propre this. Ce qui peut parfois poser quelques soucis si l’on ne fait pas attention :

Dans cet exemple, le premier this que nous rencontrons fait référence à l’objet obj. Jusqu’ici, il n’y a pas de soucis, c’est ce que l’on a vu précédemment. Par contre, dans la fonction de callback de setTimeout, this ne fait pas référence à l’objet obj, mais à l’objet global. Pourquoi ? Et bien c’est exactement le même cas que l’affectation d’une méthode d’un objet à une variable vu précédemment. Le lien qui existe avec l’objet est “brisé”. En effet, lors de l’appel de cette fonction, aucun accesseur de propriété n’est utilisé. Pour résoudre ce problème, nous devons “sauvegarder” la valeur de this comme ceci :

Avec ECMAScript 6, il est possible de résoudre simplement ce problème en utilisant les fonctions fléchées. Une fonction fléchée contrairement aux autres fonctions ne possède pas sa propre valeur this. La valeur de this à l’intérieur d’une fonction fléchée fait référence au this du parent. Voyons un exemple :

La valeur de this dans la fonction fléchée fait bien référence au this du parent à savoir celui qui se trouve dans la fonction test.

Injection de this

Avant de terminer cet article, nous allons voir qu’il est possible d’injecter la valeur de this lors de l’appel d’une fonction. Nous allons pour cela voir trois méthodes qui sont call, apply et bind.

call

La méthode call permet de faire appel à une fonction en lui fournissant comme paramètre la valeur de this ainsi que la liste des arguments de la fonction :

Voici un exemple :

Le premier paramètre de la méthode call est la valeur de this, suivi des arguments de la fonction. Ainsi lors de l’appel à la fonction add via la méthode call, la valeur de this fera référence à l’objet obj. Si nous appelons directement la fonction add une erreur se produit :

La valeur de this dans la fonction add fait référence cette fois-ci à l’objet global. Comme il ne possède pas de propriété values, une erreur se produit.

apply

La méthode apply fonctionne de la même façon que la méthode call à la différence que la liste des arguments n’est pas fournie individuellement, mais sous la forme d’un tableau :

Reprenons l’exemple précédent :

bind

Tout comme call et apply , bind permet d’injecter la valeur de this, mais contrairement aux deux autres méthodes qui appellent la fonction, bind en créer une nouvelle. La méthode bind possède la même signature que la méthode call :

Reprenons l’exemple précédemment :

Peu importe la façon dont sera appelée la fonction créée, la valeur de this à l’intérieur de celle-ci sera toujours celle fournie à la méthode bind .

Pour conclure

J’espère que vous comprenez maintenant le fonctionnement de l’opérateur this et les différentes valeurs que celui-ci peut prendre suivant le contexte dans lequel il est utilisé. Pour résumer, il y a cinq choses que vous devez retenir afin de ne plus faire d’erreurs :

  • this fait référence à ce qui se trouve à gauche d’un accesseur de propriété que ce soit la notation point ” .” ou crochets ” []“;
  • Si aucun accesseur de propriété est utilisé, this fait référence à l’objet global ( window ou global );
  • Dans un constructeur (via l’appel à l’opérateur new), this fait référence à l’objet qui vient d’être créé;
  • Les fonctions fléchées ne possèdent pas de this;
  • Les méthodes call , apply et bind permettent d’injecter la valeur de this.

Si jamais vous avez des questions, n’hésitez surtout pas à les poser en commentaires .

2 réflexions au sujet de « Javascript : l’opérateur this »

    1. C’est vrai qu’avec du recul c’est peut-être mieux d’utiliser le terme “mot clé” plutôt qu’opérateur puisque celui-ci n’accepte pas d’opérandes. Surement un abus de langage, puisque même la doc MDN utilise le terme opérateur 🙂 .

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.