2011-03-17 17 views
10

Acabo de empezar a usar oop en javascript y me encontré con algunos problemas al tratar de acceder a un método desde dentro de otro método.objeto javascript, problema de auto referencia

aquí está el código que tenía:

var Game = { 
initialize: function() { 
    if (canvas.isSupported()) { 
     sprites[0] = new Player(); 

     this.update(); 
    } 
}, 

update: function() { 
    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].update(); 
    } 

    this.draw(); 
}, 

draw: function() { 
    this.clear(); 

    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].draw(); 
    } 

    setTimeout(this.update, 10); 
}, 

clear: function() { 
    canvas.context.clearRect(0, 0, canvas.element.width, canvas.element.height); 
} 

}

pero llamando a la Game.update() da un error que el método empate no está definido. No he podido encontrar una solución real para esto. finalmente me encontré con este How to call a method inside a javascript object donde la respuesta parece ser que necesito segura la referencia this como: var _this = this; pero no pude conseguir que funcione en notación literal, por lo que cambió el código de constructor de objeto (supongo así es como se llama) y agregó la variable.

entonces cambió

this.draw(); 

a

_this.draw(); 

y funcionó.

aunque el

this.clear(); 

y la this.update() siguen siendo los mismos, nunca parecían dar errores en el primer lugar.

¿Alguien puede explicar por qué es esto? y tal vez apuntarme a una mejor solución? gracias de antemano.

actualización

Esto es lo que debe ser:

var Game = function() { 
var _this = this; 

this.initialize = function() { 
    if (canvas.isSupported()) { 
     sprites[0] = new Player(); 

     this.update(); 
    } 
} 

this.update = function() { 
    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].update(); 
    } 

    this.draw(); 
} 

this.draw = function() { 
    this.clear(); 

    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].draw(); 
    } 


    setTimeout(function() { _this.update(); }, 10); 
} 

this.clear = function() { 
    canvas.context.clearRect(0, 0, canvas.element.width, canvas.element.height); 
} 

}

+0

¿Podría mostrar el código completo que funcionó? –

+3

+1 por ser increíble y publicar su actualización. Esta publicación finalmente concretó las diferencias en los métodos alternativos de espaciado de nombres. Me hiciste un mejor codificador hoy. :) – Evildonald

Respuesta

14

Al hacer esto:

setTimeout(this.update, 10); 

que qué pasan correctamente la referencia a la función de "actualización" para el sistema, pero cuando el navegador se llama en realidad la función más tarde, no tendrá idea de qué se supone que es this. Lo que puede hacer en su lugar es la siguiente:

var me = this; 
setTimeout(function() { me.update(); }, 10); 

que se asegurará de que cuando "actualización" se llama, se le llamará con this ha establecido correctamente como una referencia a su objeto.

A diferencia de otros idiomas, el hecho de que una función se defina inicialmente como una propiedad de un objeto no vincula intrínsecamente la función con ese objeto. De la misma manera que si usted tenía un objeto con un propertly eso es un simple número:

maxLength: 25, 

así el valor "25" no va a tener nada en particular que ver con el objeto; es solo un valor. En JavaScript, las funciones también son valores. Por lo tanto, es responsabilidad del programador asegurarse de que this se establezca en algo apropiado cada vez que se llame a una función de alguna manera "especial".

+0

¡Gracias por el voto a favor del drive-by, amigo! – Pointy

+0

Umm, perdón por eso. No recuerdo haber votado. Debe haber sido un clic perdido. – RoToRa

+0

Puede que no hayas sido tú, @RoToRa, probablemente seguirá siendo un misterio :-) – Pointy

0

Es problema es que se utiliza un objeto literal en lugar de una instancia de objeto

tratar de hacer de esta manera en su lugar:

var Game = function() { 
    this.initialize = function() { 
    if (canvas.isSupported()) { 
     sprites[0] = new Player(); 
     this.update(); 
    } 
    }; 
    this.update = function() { 
    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].update(); 
    } 

    this.draw(); 
    }; 

    this.draw = function() { 
    this.clear(); 

    for (var i = 0; i < sprites.length; i++) { 
     sprites[i].draw(); 
    } 

    setTimeout(this.update, 10); 
    }; 

    this.clear = function() { 
    canvas.context.clearRect(0, 0, canvas.element.width, canvas.element.height); 
    }; 
} 

ahora usan:

var myGame = new Game(); 
+0

Solo parte del problema, creo ... – Pointy

+2

Una referencia muy buena para 'esto': http://bonsaiden.github.com/JavaScript-Garden/#function.this – adrian

+1

@Pointy: cierto, el setTimeout es está destinado a fallar, pero parece que está cubriendo eso :) –

Cuestiones relacionadas