| Summary: Ce tutoriel présente les principes fondamentaux de la portée et la visibilité des variables en JavaScript. |
| Author: Jozef Sakalos (Traduction: Damien Serve) |
| Published: August 23, 2007 (Traduction: 2008-05-20) |
| Ext Version: 1.1+ / 2.0+ |
Languages: English Chinese Korean French Turkish Italian
|
Contents |
Avant de commencerLa meilleure façon d'étudier ce tutoriel est d'avoir Firefox avec Firebug sous la main. De cette façon vous pourrez tester les exemples du tutoriel tout de suite.
Installez-les tous les deux si ce n'est déjà fait.
Définitionportée (NdT: garder à l'esprit sa traduction anglaise scope)
1. (nom) un périmètre dans lequel quelque chose agit, opère ou a le contrôle [1]
2. (nom) En programmation, la visibilité des variables au sein d'un programme; par exemple si une fonction peut utiliser une variable créée dans une autre fonction [2]
Donc de quoi allons-nous parler ? Nous allons trouver si et où une variable est disponible lorsque nous exécutons des fonctions, et ce que veut dire une personne qui dit "c'est un problème de portée" ou "ça s'exécute dans un mauvais scope" ou similaire.
C'est partiChaque fonction que vous définissez en JavaScript est une méthode d'un objet. Même si vous l'écrivez comme suit :
function fn() { alert(11); }
Il doit plaisanter, vous dites-vous. Mais vous pouvez faire une expérience très simple pour vous prouver que c'est vrai. Vous n'avez besoin d'aucun fichier javascript, serveur ou code html pour ce faire. Ouvrez juste Firefox, ouvrez la fenêtre Firebug du bas et cliquez sur l'onglet console. Juste au-dessus de la barre de statut de Firefox vous pouvez voir une ligne commençant par >>> et dans laquelle vous pouvez saisir du texte. Si vous ne voyez pas les >>> en bas de l'onglet console, allez dans le menu Options et décochez l'option 'Ligne de commande plus large' ('Larger command line'). Tapez ceci :
function fn() { alert(11); };
puis Entrée. Rien ne se passe, d'accord? Tout ce que vous avez fait est définir la fonction fn. Maintenant essayez :
fn();
et Entrée. Vous avez une alerte avec 11? Jusqu'ici tout va bien. Maintenant essayez :
window.fn(); this.fn();
Vous avez la même chose? C'est parce qu'en fait la fonction fn est une méthode de l'objet window. La deuxième ligne vous donne la preuve que la variable this est égale à l'objet window. Le fait de ne pas avoir à appeler la fonction via window.myFunction(...) est juste par commodité, pour faciliter le travail de programmeurs paresseux.
L'objet windowL'objet window est toujours là--vous pouvez y penser comme la fenêtre du navigateur. Il contient tout les autres objets comme l'objet document et toutes les variables définies comme globales.
Vous pouvez ouvrir Firebug, aller dans l'onglet script, et saisir window dans la boîte "New watch expression..." du côté droit de Firebug, puis presser Entrée. Vous pouvez alors explorer l'objet window pour vous figurer ce qu'il contient. Vous pouvez également juste cliquer sur l'onglet DOM et voir la même information sur l'objet window.
En particulier trouvezla fonction fn que nous avons défini plus tôt.
Chaque frame ou iframe possède son propre objet window, son propre espace global.
Comprendre la portéeMaintenant compliquons un petit peu. Retournez à la console Firebug et saisissez :
var o1 = {testvar:22, fun:function() { alert('o1: ' + this.testvar); }}; var o2 = {testvar:33, fun:function() { alert('o2: ' + this.testvar); }};
Qu'avons nous fait? Nous avons défini des objets o1 et o2 chacun avec les mêmes propriétés et méthodes sauf que la propriété contient des valeurs différentes.
Essayez maintenant :
fun(); window.fun(); this.fun();
Erreurs, hein? C'est sûr, l'objet window (qui est égal à this) n'a pas de méthode fun. Essayez ce qui suit :
o1.fun(); o2.fun();
Vous avez 22 et 33? C'est bien!
Et maintenant la dernière complication. Nous avons ici des fonctions primitives que vous ne désirez pas saisir pour chacun de vos objets, mais disons que o1.fun est une fonction évoluée et longue que vous avez mis une semaine à développer et qui fonctionne maintenant. Imaginez qu'elle contienne 100 lignes parsemées de this. Alors comment exécuteriez-vous o1.fun mais en ayant this qui pointe sur o2? Essayez ce qui suit :
o1.fun.call(o2);
Vous voyez? Vous avez forcé la variable this à pointer sur o2 lors de l'exécution de la méthode fun de l'objet o1, en d'autres mots et de façon plus scolaire : la méthode o1.fun() s'exécute dans la portée de l'objet o2.
Vous pouvez penser à la portée comme à la valeur de la variable this lors de l'exécution d'une fonction, d'une méthode ou d'un objet.
Visibilité des variablesLa visibilité des variables est fortement liée au sujet des portées de variables. Nous savons déjà que les variables (les fonctions sont également des variables) définies en-dehors de tout objet ou fonction sont globales ou, techniquement, qu'elles sont des propriétés de l'objet global window.
Les variables globales sont visibles partout; à l'intérieur ou à l'extérieur de toutes fonctions. Si vous modifiez la valeur d'une variable globale à l'intérieur d'une fonction, les autres fonctions verront la valeur modifiée.
Nous savons également que les objets peuvent avoir leurs propres propriétés (comme testvar ci-dessus) visibles de l'intérieur et de l'extérieur de l'objet. Essayez:
alert(o1.testvar); // accès à la propriété testvar d'o1 depuis l'extérieur
L'accès depuis l'extérieure a déjà été démontré dans les méthodes fun des deux objets de test.
La dernière pièce du puzzle est les variables locales définies à l'intérieur de fonctions avec le mot-clé var:
i = 44; function fn2() { var i = 55; alert(i); } fn2();
Qu'allez-vous obtenir? C'est cela, 55. La variable i définie dans fn2 est locale à la fonction fn2 et n'a rien à voir avec la variable globale i qui est égale à 44.
Mais:
alert(i);
Vous donnera 44 car nous accédons maintenant à la variable globale i.
J'espère que cela éclaircit un peu le sujet des portées et visibilités de variables.
Pour aller plus loin: