This et new, une relation étroite
Un objet JavaScript est créé avec le mot réservé new. Le mot this désigne ses attributs.
Plus précisement, l'objet est défini comme une fonction. Selon que l'on fasse un appel ou que l'on crée une instance avec new, la définition s'utilise comme une fonction ou comme un objet. Nous allons le voir en détails avec des exemples.
Changement d'une variable globale dans un objet
Si l'on assigne une variable dans un objet, que l'on fasse référence à celui-ci comme un objet ou comme une fonction, la variable est modifiée au niveau global.
var test1 = 10;
function classe1()
{
test1 = 20;
}
new classe1();
document.write(test1);
test1 = 50;
classe1();
document.write(test1);
Ce que l'on doit remarquer est qu'on a créé un objet avec new Classe1 sans assigner une variable et donc sans avoir de référence à l'instance créée: la définition est devenue un objet. Ensuite on peut encore faire référence à la définition par un appel de fonction. Comme entretemps on a modifié la valeur de la variable test1, on vérifie que l'appel a bien assigné de nouveau cette même variable.
Tant que l'on n'a pas assigné l'instance à une variable toutefois, la déclaration sert uniquement de conteneur où l'on peut modifier des variables globales, et utiliser des variables locales pour les calculs internes. Si l'on veut appeler une méthode ou accéder à un attribut de façon externe, il faudra évidemment une référence à cette instance.
This et les variables globales
Essayons le mot réservé this.
var test2 = 10;
function classe2()
{
test2 = 20; // on change la variable globale
this.test2 = 30; // on change la variable locale, ce qu'on croit
}
classe2();
document.write(test2);
C'est la variable globale qui a été modifiée avec l'instruction this.test2 = 30.
Localisation avec var
Le mot réservé var déclare une variable avec une visibilité locale à la fonction. Si l'on utilise this avec cette variable, est-elle locale ou globale? On vérifie...
function classe3()
{
var test3 = 10;
return(this.test3);
}
var x = classe3();
document.write("x= " + x);
Le résultat est indéfini parce que test3 n'existe par au niveau global et que classe3 n'est en fait pas un objet mais une fonction.
Combiner var et this
Nous essayons d'utiliser var d'abord pour limiter la visibilité à la définition, puis this pour faire référence au conteneur, mais cela va-t-il limiter la visibilité au conteneur?
var test4 = 10;
function classe4()
{
var test4 = 20;
this.test4 = 30;
test4 = 40;
}
classe4();
document.write("test4= " + test4);
Ce n'est manifestement pas le cas, sans this, on voit que l'assignation modifie le contenu de la variable locale, mais this a un effet différent: l'assignement se fait sur la variable globale!
Pour le confirmer on a ensuite ajouté un assignement à 40 sans this qui lui modifie bien la variable locale.
Sans l'utilisation de this
On vérifie encore que la variable globale reste inchangée quand on n'utilise pas this.
var test5 = 10;
function classe5()
{
var test5 = 20;
}
classe5();
document.write("test5= " + test5);
Ce qui est le cas, la variable vaut 10, la valeur assignée globalement.
Utilisation de new
Avec new on crée une instance, donc la fonction devient la définition d'un objet, tout en restant utilisable comme fonction par ailleurs.
var test6 = 10;
function classe6()
{
var test6 = 20;
this.test6 = 30;
}
x = new classe6();
document.write("test6= " + test6);
La variable "test6" a été changée localement grâce à this et parce que nous avons créé un objet avec new.
La conclusion de toutes ces démonstrations est que le mot réservé this est inopérant quand on appelle la fonction, ou plutôt il s'applique au scope global à défaut d'un autre containeur, et donc qu'une fonction n'est un objet que lorsqu'on utilise le mot réservé new. Si la fonction était contenue dans une autre fonction this s'appliquera toujours au scope global. Démonstration:
var test7 = 10;
function classe8()
{
function classe7()
{
this.test7 = 50;
}
classe7();
}
x = classe8();
document.write("test7= " + test7);
Si l'on veut que la visibilité de this soit limitée à "classe7", il faudra déclarer new classe7() dans "classe8" et aussi new classe8().
var test8 = 10;
function classe8()
{
function classe7()
{
this.test8 = 50;
}
new classe7();
}
x = new classe8();
document.write("test8= " + test8);
Donc les variables contenues dans la définition d'une fonction deviennent des attributs quand on en fait un objet. Ces attributs sont publics, mais on crée l'équivalent d'attributs privés en utilisant var et sans utiliser this. Ainsi JavaScript devient orienté-objets par le seul fait du mot new!
En conclusion, la façon dont les objets sont définis en JavaScript leur donne une universalité qui facilite la réutilisation du code pour des usages différents, ce que l'habilité du programmeur lui permettra d'exploiter. Aucun autre langage n'offre cette liberté.
Voir aussi
Les objets dynamiques de JavaScript. Notions essentielles. Instances, attributs, méthodes.