objeto this, objeto that...

4 views
Skip to first unread message

Javier Infante

unread,
May 21, 2011, 10:41:44 AM5/21/11
to jsmeetu...@googlegroups.com
Aupa!

Bueno por fin he sacado un ratito y he encontrado el caos mental que
tenía con la utilización de this en objetos sin instanciar en jQuery
(minuto 3 de la charla del hyperandroid del otro día).

Aquí el código, simple, sin jQuery y muy chorra.

<html>
<head>
<script type="text/javascript">
var miObj = {
input : null,
button : null,
load : function() {
var that = miObj; // Si funciona
//var that = this; // No funciona :(
that.input = document.getElementById("numero");
that.button = document.getElementById("action");
that.button.addEventListener("click",that.calcula,true);
},
calcula : function() {
var that = miObj; // Si funciona
//var that = this; // No funciona :(
that.button.value = that.input.value * that.input.value;

}
};

window.addEventListener("load",miObj.load,true);

</script>
</head>
<body>
<input type="text" id="numero" /><br />
<input type="button" id="action" value="Al cuadrado" />
</body>
</html>


Creo que la movida es que, al invocar un método encapsulado dentro de
una variable de un módulo (o JSON u objeto simple o {} o como queráis
llamarlo), éste se ejecuta siempre en el contexto de window y no dentro
de su propio contexto...


Bueno sin más, que sabía yo que oía campanas, y ya he visto donde...
cualquier aportación o aclaración molaría ;)

venga nos vemos le miércoles.

--
jabi

hyperandroid

unread,
May 21, 2011, 11:10:59 AM5/21/11
to jsmeetu...@googlegroups.com
El tema es del onload. Luego te amplio qué ahora estoy de tiendas con
las niñas. Sí tú llamas al método está bien pero desde onload está en
contexto de window porque le pasas la función del objeto.

hyperandroid

unread,
May 21, 2011, 4:21:21 PM5/21/11
to jsmeetu...@googlegroups.com
Aupa Javi,

como te decía antes, el problema está en qué espera el método addEventListener, es decir, función.
Cuando pasas como parámetro un método de un objeto, cuando llames a este método, ya no está en el contexto del objeto al que pertenece, sino en el del objeto que invoque el método. En este caso, quien ejecuta el método es window, el propietario de addEventListener.

Si quisieras volver a contextualizar el método con el objeto concreto, deberías tener por un lado referencia del objeto, y en lugar de invocar el método directamente, hacer: metodo.call( objeto, para1, param2 ... ) o metodo.apply( objeto, [param1, param2,...] );
Por ejemplo:

si tenemos este objeto,

var miObj = {

       input : "input",

       button : "button",

       load : function() {

               this.input= 55;

       },

       calcula : function() {

               var that = this;

               that.button.value = that.input.value * that.input.value;

       }

};


hacer miObj.load(), pone a 55 sin problemas su atributo input. Fijate que hace referencia a traves de this.
al hacer:

var fn= miObj.load;
fn();

this ya no apunto a miObj, sino al objeto desde que el que se invoca fn, es decir, window o el objeto top level que haya. Vamos, que si hacer input; input tiene valor 55 en el contexto global.

para hacer que fn vuelva a estar referido a miObj, tienes que hacer:

fn.call( miObj ); (o como no tiene parametros, puedes hacer tambien fn.apply( miObj );

Si hacer ahora miObj.input, tienes el valor 55 en el objeto.

Por tanto, sabiendo que this es el objeto que llama a una función, desde el handler del evento será window.
Si tu llamas a miObj.load, this será quien tu esperas. Si lo llama window, será window.

podrías arreglarlo, pasando a addEventListener una:
function() {
  miObj.load();
}
que hará que this en la llamada sea quien tu esperas.

Un saludo
-i 


Reply all
Reply to author
Forward
0 new messages