2010-11-12 17 views
5

yo soy un principiante en JS, y estoy sorprendido por el siguiente código:Javascript prototipo y "este" acceso en el cierre

Foo = function(arg) { 
    this.arg = arg; 
}; 

Foo.prototype = { 
    init: function() { 
     var f = function() { 
      alert("current arg: " + this.arg); // am expecting "bar", got undefined 
     } 
     f(); 
    } 
}; 

var yo = Foo("bar"); 
yo.init(); 

que se esperaba conseguir "arg actual: bar", pero tengo "actual arg: indefinido ". Noté que copiando this.arg en una variable "normal" en primer lugar, y refiriéndose esta variable en el cierre funciona:

Foo.prototype = { 
    init: function() { 
     var yo = this.arg; 
     var f = function() { 
      alert("current arg: " + yo);   } 
     f(); 
    } 
}; 

estoy haciendo algo mal, tengo expectativas equivocadas, o lo hace caer en una de las js WTF?

+0

Copiar 'this.arg' en una variable" normal "primero no hará nada diferente de lo que' this' significa para su función. – bobobobo

+0

@bobobobo Técnicamente cierto, pero ¿cuándo alguien insinuó que eso pasaría? La forma en que redactó eso podría ser engañosa. De hecho, no usó 'this' en el segundo ejemplo; el uso de la variable local "yo" crea un cierre que mantiene la referencia al objeto deseado incluso dentro de la función 'f'. – theazureshadow

Respuesta

3

Depende de cómo se invoca la función.

Si se invoca con la palabra clave new, entonces this se refiere al objeto que se está construyendo (que se devolverá implícitamente al final de la función).

Si se invoca como una función normal, this se refiere al objeto global window.

Ejemplo:

// Constructor for Foo, 
// (invoke with keyword new!) 
function Foo() 
{ 
    this.name = "Foo" ; 
} 

myFoo = new Foo() ; 
alert('myFoo ' + myFoo.name + '\n' + 'window: ' + window.name) ; // window.name will be empty 

// now if we invoke Foo() WITHOUT keyword NEW 
// then all references to `this` inside the 
// function Foo will be to the 
// __global window object__, i.e. the global window 
// object will get clobbered with new properties it shouldn't 
// have! (.name!) 

Foo() ; // incorrect invokation style! 
alert('myFoo ' + myFoo.name + '\n' + 'window: ' + window.name) ; 

JavaScript no tiene "constructores" de por sí, la única manera de JavaScript sabe que su function es en realidad un "constructor" es el estilo invocación (es decir, que el uso de palabras clave cuando se ejecutan las new it)

4

Las funciones de vainilla se ejecutarán con this refiriéndose a window. Su segunda pieza de código es un ejemplo perfecto de cómo solucionar este problema utilizando cierres.

(También puede utilizar call y apply llamar a una función con un contexto particular.)

+0

Ah, esto explica el comportamiento. Gracias ! –

+0

Es una pena que los votos a favor sean anónimos. A quien haya votado negativamente, agradecería un comentario :) – theazureshadow