Foros del Web » Programando para Internet » Javascript »

setTimeout en objeto

Estas en el tema de setTimeout en objeto en el foro de Javascript en Foros del Web. Hola a todos. Tengo una duda sobre el siguiente codigo. Es algo asi: Código HTML: <script> function AA() { this.BB = BB; } function BB() ...
  #1 (permalink)  
Antiguo 08/08/2007, 13:44
 
Fecha de Ingreso: marzo-2007
Mensajes: 135
Antigüedad: 17 años, 1 mes
Puntos: 0
Pregunta setTimeout en objeto

Hola a todos. Tengo una duda sobre el siguiente codigo. Es algo asi:

Código HTML:
<script>

function AA() {

this.BB = BB;
}
function BB() {

_temp = setTimeout ("this.BB()",1000);
}

var CC = new AA();
window.onload = function () {

CC.BB();
}
</script> 
Con este codigo no inicia el temporizador, vamos no funciona. Pero si
la linea _temp = setTimeout ("this.BB()",1000) la escribo asi:
_temp = setTimeout ("CC.BB()",1000);
entonces si que me funciona, por que es esto ???

Muchas gracias.
  #2 (permalink)  
Antiguo 08/08/2007, 16:11
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Re: setTimeout en objeto

Hola miguelcubas:

Hace tiempo me encontré con el mismo problema que tú, exactamente el mismo planteamiento. De hecho si creas más instancias de AA() entonces no hay solución (aparentemente).

El error es entendible, ocurre que una llamada a CC.BB() va a funcionar en todo momento, incluso una vez acabada la ejecución del script. Esto es porque CC está definido para todo el ámbito de la página mientras esté abierta. Sin embargo this sólo está definido para el ámbito de ejecución de la función (o método en sí). Después ese this no significa nada ni referencia a nada de nada. Por lo tanto, después de un segundo, this no tiene valor ni apunta a nada.

Lo resolví haciendo la variable CC global, tal y como lo tienes tú. Pero, ¿cómo sabemos dentro del método qué nombre tiene esa variable de ámbito global que contiene la instancia del objeto? Como ves, estoy por saberlo. Para FF funciona, para IE aún no encuentro solución.




Lo que hice fue crearle un número de serie con Math.random() y almacenar la misma instancia en un array que es de ámbito global. Lo tienes todo en este hilo: aporte: programacion secuencial. Entonces, éste código (que es parecido al que tú tienes):
Código PHP:
function coxe() {
    
this.velocidad=50;
    
this.frenar=function() {
        if(
this.velocidad>0) {
            
this.velocidad--;
            
setTimeout("this.frenar()"100);
        }
    }

Se ha de transformar en éste:
Código PHP:
var coxes=new Array();
function 
coxe() {
    
//crear serial para guardar el objeto globalmente
    
do {
        
this.serial=parseInt(Math.random()*1000);
    } while(
coxes[this.serial]!=undefined);
    
coxes[this.serial]=this;
    
this.velocidad=50;
    
this.frenar=function() {
        if(
this.velocidad>0) {
            
this.velocidad--;
            
setTimeout("coxes["+this.serial+"].frenar()"100);
        }
    }

Y así coxes[serialDeUnCoxe] apuntará a la instancia de coxe() que tenga ese serial. Entonces sí que podemos hacer fácilmente el bucle, utilizando un array de ámbito global. Otra cosa es que el serial creado coincida con otro que ya ha sido creado (ojo si creas 10 millones de instancias de coxe() ).



Bueno, si a alguien se le ocurre otra idea, todavía está a tiempo de postear! jeje.




Un saludo.
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #3 (permalink)  
Antiguo 08/08/2007, 17:10
Avatar de MaBoRaK  
Fecha de Ingreso: abril-2003
Ubicación: La Paz - Bolivia
Mensajes: 2.003
Antigüedad: 21 años
Puntos: 35
Re: setTimeout en objeto

loading.............

Es un tiipico problema de closures

Código PHP:
function AA() {

this.BB BB;
}
function 
BB() {

var 
oThis=this;
_temp setTimeout (function(){oThis.BB();},1000);
}

var 
CC = new AA();
window.onload = function () {

CC.BB();

De esta forma deberías tener la llamada a tu funcion ENCAPSULADA.
Léase: http://developer.mozilla.org/es/docs...%A1s_flexibles

y

http://blog.scriptia.net/articulos/2...esperados.html
:p



conection closed.
__________________

Maborak Technologies
  #4 (permalink)  
Antiguo 08/08/2007, 17:18
Avatar de MaBoRaK  
Fecha de Ingreso: abril-2003
Ubicación: La Paz - Bolivia
Mensajes: 2.003
Antigüedad: 21 años
Puntos: 35
Re: setTimeout en objeto

loading.........

No se porque agregas una funcion simple a un método... podrías hacer

Código PHP:
AA.prototype.BB=function() 
o bien

Código PHP:
function AA() {

this.BB BB.apply(this);

Con eso convertirías a tu funcion BB en un método mas de la clase.

connection closed.
__________________

Maborak Technologies
  #5 (permalink)  
Antiguo 08/08/2007, 19:40
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Re: setTimeout en objeto




Muy buena respuesta MaBoRaK, llevaba pero que mucho tiempo con este problema, y no sabía cómo resolverlo de manera elegante (mira si me había complicado en mi desesperación...).


Así que se trata de la tontería de var oThis=this; y de los closures...
Me he fijado que el setTimeout no se puede escribir de otra manera... Si escribimos en String "oThis.BB()" no funcionará, y si la función de dentro del setTimeout la sacamos fuera (con un nombre) tampoco funcionara. Es que, como ves, no entiendo muy bien el ámbito de la variable oThis. Está disponible para todo el método BB(), ¿y cómo es que está disponible después en cualquier momento para el setTimeout()? Si es de ámbito global, ¿por qué entonces si añadimos una nueva instancia de AA() no se sobreescribe? Es como si el closure fuera un paréntesis cerrado en sí mismo que funciona él solito y para él solito



Por cierto, buenísimos los links, los he repasado de pé a pá. Lo único que hay que tener cuidado es que en http://developer.mozilla.org mucho contenido es para javascript 1.5 (incluso 1.7), y lo evito leer, para no frustrarme demasiado. Pero esa parte de los objetos no la había leído.


Un saludo y gracias.
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #6 (permalink)  
Antiguo 09/08/2007, 14:06
Avatar de MaBoRaK  
Fecha de Ingreso: abril-2003
Ubicación: La Paz - Bolivia
Mensajes: 2.003
Antigüedad: 21 años
Puntos: 35
Re: setTimeout en objeto

loading.............

Cita:
Si escribimos en String "oThis.BB()" no funcionará, y si la función de dentro del setTimeout la sacamos fuera (con un nombre) tampoco funcionara. Es que, como ves, no entiendo muy bien el ámbito de la variable oThis. Está disponible para todo el método BB(), ¿y cómo es que está disponible después en cualquier momento para el setTimeout()? Si es de ámbito global
Pasa que si haces var oThis=this; no es una variable global sinó local es por eso que si en settimeout llamas a a una funcion "virtual" y dentro a Othis, primero busca en las variables locales (variables dentro de un método) y luego directamente en window asi que si pones la funcion fuera de la clase entonces buscará directamente en window.
Cita:
, ¿por qué entonces si añadimos una nueva instancia de AA() no se sobreescribe?
Porque en cada nueva instancia los métodos tienen nuevas variables locales.

Algo que podría servirte es esto:

Código PHP:
 var closure=function(options)
 {
         var 
method      =options.method;
         var 
instance=options.instance;
         var 
args        =(options.args || (typeof options.args=="number" && options.args===0))?options.args:false;
         var 
_function=options.Function || false;
         var 
isArr       =options.args_is_array || false;
         var 
_event      =options.event || false;
         var 
rf          =options.Return || false;
         return function(
hEvent)
         {
                 var 
argss=(args===false)?false:((args.isArray && isArr===false)?args:[args]);
                 var 
param=(_event)?[(hEvent || window.event)].concat(argss):argss;
                 if(
_function===false)
                 {
                         
method.apply(instance,param || [null]);
                 }
                 else
                 {
                         
_function.apply(_function,param || [null]);
                 }
                 return 
rf;
         };
 }; 
Con esta función puedes
  1. Resolver los closures
  2. Ejecutar métodos de una clase A en un ambito de la clase B
  3. Crear funciones "virtuales" (algo(function(){},333)) instanciadas para la ejecución en la clase que quieras.
  4. llamar a funciones/métodos con parámetros

Documentación.
Código:
 @param {Object} options = {
               method  :Method,
               instance:Instance,
               Function:Function,
               arguments:Array["sample",var,222]
               event   :true || false,                 #Expand event?
               argument_is_array:true || false         #Arguments is Array?
       } Options
Samples

Llamar a una funcion con parámetros
Código PHP:
var algo=function(parametro){alert(parametro)};
objetoDOM.onclick=closure({Function:algo,args:232323}); 
Ejecutar métodos de una clase A en un ambito de la clase B
Código PHP:
var algo=function(parametro){alert("esta funcion se ejecuta como parte de la clase A")};
objetoDOM.onclick=closure({instance:classA,method:algo,args:232323}); // con un solo parametro
objetoDOM.onclick=closure({instance:classB,method:classB.algunMethod,args:[1,2,3,4,5]}); // con 5 parámetros 
SI usas eventos necesitaras en mozilla expandir el evento
Código PHP:
var algo=function(parametro){alert("esta funcion se ejecuta como parte de la clase A")};
objetoDOM.onclick=closure({instance:classA,method:algo,args:232323}); // con un solo parametro
objetoDOM.onclick=closure({instance:classB,method:classB.algunMethod,args:[1,2,3,4,5],event:true}); // con 5 parámetros 
Y otros usos mas....

Y se puede resumir esta funcion a un prototipo de Function. que alguien lo haga :p



connection closed.
__________________

Maborak Technologies
  #7 (permalink)  
Antiguo 10/08/2007, 13:03
Avatar de derkenuke
Colaborador
 
Fecha de Ingreso: octubre-2003
Ubicación: self.location.href
Mensajes: 2.665
Antigüedad: 20 años, 6 meses
Puntos: 45
Re: setTimeout en objeto

Madre mía MaBoRaK, te has pasado! jeje.

Tendré que tomarme mi tiempo para ver las posibilidades del código, y su aplicación a todos los campos... tiene mucho jugo al parecer.


Por lo menos ya he entendido lo de los closures.


Por cierto cuando dije
Cita:
Iniciado por derkeNuke
¿y cómo es que está disponible después en cualquier momento para el setTimeout()? Si es de ámbito global, ¿por qué entonces si añadimos una nueva instancia de AA() no se sobreescribe?
Lo que quería decir es: "si es que fuera de ámbito global", está claro que no es de ámbito global esa variable .



Bueno, pues a ponerlo en práctica, muchas gracias!
__________________
- Haz preguntas inteligentes, y obtendrás más y mejores respuestas.
- Antes de postearlo Inténtalo y Búscalo.
- Escribe correctamente tus mensajes.
  #8 (permalink)  
Antiguo 10/08/2007, 13:34
Avatar de MaBoRaK  
Fecha de Ingreso: abril-2003
Ubicación: La Paz - Bolivia
Mensajes: 2.003
Antigüedad: 21 años
Puntos: 35
Re: setTimeout en objeto

loading..........


Bueno yo lo he llamado closures... porque encierra a los closures,instancias y todo eso.... pero en realidad un closure (para no quedar mal) es cuando tus datos de ingreso cambian al de lectura, el típico ejemplo.


Código PHP:
for(var i=0;i<22;i++)
{
 
algo.onclick=function(){
   
alert(i);
 }

En teoría cada alert debería tener 1,2,3,4,5,6,7.. etc. pero no siempre te sale 22, no se toma el valor actual sinó el valor final de la variable local o global.......... pero igual a todos esos problemitas llamemosle closures :D


connection closed.
__________________

Maborak Technologies
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 18:13.