Pensé que tenía una comprensión razonable del objeto this
en JavaScript. Cuando trato con objetos, devoluciones de llamada, y eventos y manejadores, no he tenido problemas con él desde tiempos inmemoriales. Ahora, sin embargo, todo ha cambiado.Cierre de JavaScript y este objeto
Me he enamorado locamente de JavaScript. JS puro, es decir, no jQuery, prototype.js, dojo ... Así que, naturalmente, me he acostumbrado a usar cierres. En algunos casos, sin embargo, this
me está tomando por sorpresa aquí. Tome este fragmento de uno:
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
En los tres casos, this
registros como el objeto de la ventana. Es una solución fácil, por supuesto:
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
Esta corrección funciona, lo pongo aquí para evitar personas que responden esto, sin explicar lo que necesito saber: ¿por qué es esto comporta como lo hace aquí?
asegura que la persona que llama es efectivamente el objeto al que pertenece el cierre. Lo que no entiendo es esto: Efectivamente, this
apunta al objeto ventana en el primer caso, pero en otros casos, no debería. Intenté iniciar sesión en this
en la función makeClic justo antes de volver, y se registró el objeto en sí, no el objeto window
. Sin embargo, cuando se utiliza el cierre real, this
ha vuelto a señalar al objeto de ventana. ¿Por qué?
Lo único que se me ocurre es que, pasando la función anyFunc
como argumento, en realidad estoy pasando window.anyFunc
. Así que he intentado esta solución rápida:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
con los resultados esperados, this
ahora apunta a los objetos, pero una vez más: ¿Por qué? Tengo algunas ideas (theFunc
es una referencia a la función en el ámbito local [this > private: theFunc
]?), Pero estoy seguro de que hay personas aquí con mucho más conocimiento cuando se trata de JS, así que estaba esperando obtener una explicación más o enlaces a artículos que vale la pena leer de ellos ...
Gracias
actualización
Here's a fiddle, puede ser que dejé algo, pero aquí esta registra todo tipo de cosas;)
E dit/Update 2
The case that confuses me es aquí.
edición final
Ok, Esto se está poniendo un mensaje en vez desordenado. Así que para aclarar: Lo que esperaba era un comportamiento similar a esto:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
Lo que me llamó, fue que la función anyFunc
no fue declarado dentro del ámbito correcto, y por lo tanto, this
señaló al objeto de ventana. Descubrí esto leyendo un ancient scroll que encontré en algún lugar de la web.
Pero algo un poco más complicado ha sucedido porque el objeto función que ahora se conoce por globalVar fue creado con un [[alcance]] propiedad en referencia a una cadena de ámbito contiene el objeto de activación/variable que pertenece al contexto de ejecución en que fue creado (y el objeto global). Ahora el objeto Activación/Variable no se puede recolectar como basura, ya que la ejecución del objeto de función referido por globalVar necesitará agregar toda la cadena de alcance desde su propiedad [[scope]] al alcance del contexto de ejecución creado para cada llamada a eso.
Así que lo que tenía que hacer, fue simplificar en vez de complicar las cosas:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
que debería funcionar, ¿verdad?
PD: Excepto la respuesta de Alnitak, pero un agradecimiento especial a Félix Kling por toda la paciencia y la información.
realmente no conseguir lo más respuesta que un enlace a una explicación global de los cierres podrían hacerse. Este curso es una lectura excelente y debe eliminar todas las incertidumbres: http://ejohn.org/apps/learn/ –
El problema no es que no obtenga cierres. Lo que está causando los dolores de cabeza es que no estoy del todo seguro de lo que le sucede al objeto 'this' al hacer cierres de la manera en que lo hago aquí –
No puedo reproducir el comportamiento que describes. Obtengo 'DOMWindow',' Object', 'Object': http://jsfiddle.net/GErkX/, mientras que tu segundo" fix "me da 3 x' DOMWindow': http://jsfiddle.net/tZXQF/ –