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éfini 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... mais je trouve tout de même beaucoup plus logique et intuitif la possibilité de récupérer la valeur de la variable externe à la fonction comme en AS2 à tout moment même si il existe un peu plus loin dans la fonction la déclaration d'une variable locale du même nom. Reste que ce que je trouve intuitif doit peut être suivre une logique qui me dépasse :)

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 de l'AS1/AS2 et pas de l'AS3.

Voici le code javascript de test :

geshi javascript
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() ;

Faudra vraiment que je vois comment réagi Tamarin ou la M2 de ES4 sur ce genre de manipulation du scope.

Dans tous les cas Adobe semble avoir corrigé un bug existant en AS1 et AS2 et il va falloir que je cherche si je trouve pas une discussion sur le sujet au niveau des mailing list ECMAScript car je trouve ce comportement vraiment étrange.