Forums Développement Multimédia

Les formations Mediabox
Les formations Mediabox



Différence dans la portée des variables entre ActionScript2 et ActionScript3

Compatible ActionScript 3. Cliquer pour en savoir plus sur les compatibilités.Compatible ActionScript 2. Cliquer pour en savoir plus sur les compatibilités.Par ekameleon (Marc Alcaraz), le 06 avril 2008

Problèmatique

Voici un rapide petit tutoriel pour illustrer une petite différence (bug ?) entre la portée des variables en ActionScript 3 par rapport à la même portée des variables en AS2.

Je ne vais pas entrer ici dans un rappel complet sur l'utilisation du scope des variables en ECMAScript (JS ou AS) mais je me suis rendu compte d'un petit problème de portabilité entre un bout de code AS2 vers de l'AS3. Je me suis donc amusé avec un petit test à isoler ce problème.

Exemple avec portée de variable simple en AS2

var a:Number = 1 ;
 
var test:Function = function():Void
{
	trace("> first : " + a) ; // 1
	var a:Number = 2 ;
	trace("> last  : " + a) ; // 2
}
test() ;
 
// output
// > first : 1
// > last  : 2

Analysons un peu l'exemple au dessus avant de passer à l'exemple en AS3 ;)

Dans le premier test, je regarde juste la portée de la variable “a” à l'intérieur de la fonction test. Lorsque j'appelle la fonction test(), la première instruction dans la fonction cherche à récupérer la valeur d'une variable qui porte comme nom “a” … Cette variable n'existe pas en local dans la fonction (variable déclarée avec le mot clé var dans la fonction) et il n'existe non plus aucun paramètre dans la fonction qui porte comme nom “a”. Du coup le script va chercher à l'extérieur de la fonction (à l'endroit où elle est déclarée) si il existe une variable qui s'appelle “a” et forcément il trouve une adresse mémoire avec ce nom et il renvoi la valeur : 1

Jusque là tout va bien :)

Ensuite je définis dans la fonction test une variable locale avec le mot clé var et du coup si j'appelle à nouveau une variable “a” la valeur trouvé par le script sera simplement celle de la variable locale trouvée : 2

A noter que si dans l'exemple précédent si j'ajoute un argument “a” dans la définition de la fonction et que je passe une valeur dans les paramètres de la fonction au moment de l'appeler j'obtiens :

var a:Number = 1 ;
 
var test:Function = function( a:Number ):Void
{
	trace("> first : " + a) ; // 3
	var a:Number = 2 ;
	trace("> last  : " + a) ; // 2
}
test(3) ;
 
// output
// > first : 3
// > last  : 2

Dans l'exemple au dessus la portée de variable se limite à un valeur trouvée dans les paramètres de la fonction, la première valeur de “a” vaut 3, la valeur passée dans la fonction au moment de l'appeler. Pas de soucis donc à ce niveau là ;)

Le même exemple en AS3 et un petit soucis ?

var a:Number = 1 ;
 
var test:Function = function():void
{
	trace("> first : " + a) ; // undefined
	var a:Number = 2 ;
	trace("> last  : " + a) ; // 2
}
test() ;
 
// output
// > first : undefined
// > last  : 2

Contrairement à l'exemple précédent en AS2, ce code AS3 n'arrive pas à récupérer la valeur de la variable située à l'extérieur de la fonction.

Par contre si je modifie légèrement le code précédent :

var a:Number = 1 ;
 
var test:Function = function():void
{
	trace("> first : " + a) ; // 1
	// var a:Number = 2 ;
	trace("> last  : " + a) ; // 1
}
test() ;
 
// output
// > first : 1
// > last  : 1

Si je désactive avec un commentaire la déclaration d'une variable locale avec le mot clé var dans la fonction, je peux donc accéder par portée enfin à la valeur de ma variable déclarée à l'extérieur de la fonction.

Conclusion

Au final, en AS3 il est impossible d'accéder à une variable par portée située à l'extérieur d'une fonction si cette variable est déclarée plus loin dans la fonction localement avec le mot clé “var”.

Il est vrai que ce type de cas de figure est très rare en si on utilise correctement les variables locales et avec une portée.

Je me suis demandé si ce comportement est voulu par Adobe ou non en AS3 par rapport à l'AS2 ?

Il m'a suffit d'un petit test en Javascript 1.7 (avec JSDB), mais aussi en Javascript 1.5 avec Flash Media Server et son SSAS pour voir que le problème venait en fin de compte de la virtual machine AVM1 de l'AS1/AS2 et pas de l'AS3.

Voici le code javascript de test :

var a = 1 ;
 
var test = function()
{
	trace("> first : " + a) ; // undefined
	var a = 2 ;
	trace("> last  : " + a) ; // 2
}
test() ;
 
trace("---") ;
 
var a = 1 ;
 
var test = function()
{
	trace("> first : " + a) ; // 1
	//var a = 2 ;
	trace("> last  : " + a) ; // 1
}
test() ;

Dans tous les cas Adobe semble avoir corrigé un bug existant en AS1 et AS2.

En savoir plus