Comunidad de diseño web y desarrollo en internet online

Ámbito de variables en ActionScript, scope, this

Uno de los quebraderos de cabeza más frecuentes a la hora de programar con ActionScript es por qué una variable que hemos definido e iniciado bien devuelve undefined cuando se llama desde una función. Espero que esto sirva para dejarlo más claro.
Distinguiremos cuando nos referimos a la variable con y sin anteponer un this a su nombre.

Ámbito de variables en la línea del tiempo de un clip (también el principal)

Es el caso más sencillo e intuitivo al definir una variable, se define en rutaDelClip.variable.

Código :

var v1="v1";
this.v2="v2";
//Ambos traces funcionan correctamente
trace(v1);
trace(v2);

Si nos queremos referir a variables de otro clip, usamos rutas absolutas (empezando por _root) o relativas (empezando por this, mejor que por vacío) y usando propiedades como _parent. No creo que eso tenga más misterio.
Cabe añadir que también existe la posiblidad de definir variables globales

Código :

_global.myVar="valor";

Que son accesibles desde todas partes con sólo poner su nobre (en este caso myVar)

Ámbito de variables dentro de funciones

Aquí, al usar this nos estamos refiriendo al ámbito de donde hemos definido la función (el clip de película, la clase, o a lo peor, otra función).
Y al no poner nada delante del nombre de la variable, también. Pero ojo, al definir variables dentro de una función SÓLO estarán disponibles DENTRO del ámbito de la función, no se podrá acceder desde fuera. Por tanto al no poner nada delante para referirnos al nombre de una variable nos referimos o bien a una que está definida dentro de la función, o bien al ámbito de donde está definida. Aquí un ejemplo:

Código :

var v1 = "v1";//Defino la variable en el ámbito principal
function traceVars() {
   var v2 = "v2";//Sólo está disponible dentro de la función
   trace(v1);//v1 está definida en el ámbito de esa función por lo que será accesible 
   trace(this.v1);//Me estoy refiriendo al ámbito, por lo que también así es válido
   trace(v2);//Es la variable que he definido en la función, por lo que vale
   trace(this.v2);//con this delante, no estará disponible porque sólo está definida dentro de la función, no en el ámbito superior
}
traceVars();
trace(v1);//Obviamente se verá bien
trace(v2);//Sólo esta definida dentro de traceVars: undefined



Ámbito de variables en controladores de eventos

Lo mismo que para las funciones, con la diferencia de que this aquí no se refiere al ámbito, si no al objeto que sufre el evento. Si invocamos el controlador directamente (MovieClip.onEnterFrame, XML.onLoad) con this nos estaremos refiriendo al mismo MovieClip (o xml). Esto resulta particularmente útil cuando queremos referenciar un clip de una secuencia cuyo nombre no conocemos. Por ejemplo, en una secuencia de 5 botones, btn0-4:

Código :

for(i=0;i<5;i++){
        this["btn"+i].onRelease=function(){
        clip._x=this._x
        clip._y=this_y
    }
}

Que movería un clip llamado clip a las coordenadas de ese botón.
En cambio, cuando se trata de eventos disparados por un objeto listener, a quien se refiere this es al mismo listener. Con un componente Button llamado miBoton:

Código :

var listener:Object = new Object();
listener.sayHello = function() {
   trace("Hello");
};
listener.click = function() {
   this.sayHello();
};
miBoton.addEventListener("click", listener);


Llamadas anidadas: trabajo dentro de clases

Escribir dentro de una clase es como hacerlo en un mc. this o no poner nada se refiere a la instancia de la clase. Pero no tenemos los comodines _root y _parent. Por lo tanto si queremos crear una función dentro de la que haya un evento y desde él acceder a una propiedad de la clase tenemos que hacer un pequeño truco, definir una variable que referencie al ámbito de la función, ya que no poner nada dentro del evento se refiere al ámbito de la función, no al de la instancia de la clase. En un archivo llamado Prueba.as coloquen esto:

Código :

class Prueba {
   var hi = "hallo";
   function Prueba() {
   }
   function cargarXML() {
      var falsoXML:XML = new XML();
      falsoXML.load("grfx.xml");
                //
                //
      //Ésta es la línea c00l. Permite acceder al ámbito de la función, 
      //la clase desde el evento del XML
      var scope = this;
                //
                //
      falsoXML.onLoad = function() {
         trace(hi);//undefined
         trace(this.hi);//undefined
         trace(scope.hi);//hi. Así sí funciona
      };
   }
}

Y en un fla en la misma carpeta:

Código :

import Prueba
var prob:Prueba=new Prueba()
prob.cargarXML()

Esparo que les haya servido.

¿Sabes SQL? ¿No-SQL? Aprende MySQL, PostgreSQL, MongoDB, Redis y más con el Curso Profesional de Bases de Datos que empieza el martes, en vivo.

Publica tu comentario

o puedes...

¿Estás registrado en Cristalab y quieres
publicar tu URL y avatar?

¿No estás registrado aún pero quieres hacerlo antes de publicar tu comentario?

Registrate