2009-04-02 7 views
25

El comportamiento de "esto" cuando se llama a la función bar me desconcierta. Vea el código a continuación. ¿Hay alguna manera de organizar "esto" para que sea una simple instancia de objeto js antiguo cuando se llama a la barra desde un manejador de clics, en lugar de ser el elemento html?jQuery/JavaScript "this" puntero confusión

// a class with a method 

function foo() { 

    this.bar(); // when called here, "this" is the foo instance 

    var barf = this.bar; 
    barf(); // when called here, "this" is the global object 

    // when called from a click, "this" is the html element 
    $("#thing").after($("<div>click me</div>").click(barf)); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
+0

Por favor explique el '" this "es la instancia de foo'. El siguiente jsfiddle (http://jsfiddle.net/yY6fp/1/) demuestra que 'this' en' this.bar() 'se evalúa como el objeto' window' (global). –

Respuesta

33

Bienvenido al mundo de javascript! : D

Se ha adentrado en el ámbito de alcance y cierre de JavaScript.

Para la respuesta corta:

this.bar() 

se ejecuta bajo el alcance de foo, (como este se refiere a foo)

var barf = this.bar; 
barf(); 

se ejecuta bajo la alcance global.

this.bar básicamente significa:

ejecutar la función señalado por this.bar, bajo el alcance de esta (foo). Cuando copió this.bar a barf, y ejecutar barf. Javascript entendido como, ejecuta la función apuntada por barf, y como no hay este, solo se ejecuta en alcance global.

Para corregir esto, se puede cambiar

barf(); 

a algo como esto:

barf.apply(this); 

Esto le dice Javascript para unir el alcance de esta a vomitar antes de ejecutarlo.

Para eventos jquery, deberá usar una función anónima o extender la función de vinculación en prototipo para admitir el alcance.

Para más información:

+2

no estoy 100% seguro de la terminología a mí mismo, pero creo que esta respuesta (y los recursos vinculados a) son confusas 'alcance' con 'contexto de ejecución'. El objeto señalado por 'this' es * el contexto de ejecución *, y es completamente independiente de * scope * (qué cierres tienen que ver con). El alcance se determina en el momento de creación de una función y determina qué variables puede ver la función; El contexto de ejecución se determina cada vez que se llama a la función y determina a qué se refiere 'this'. Reemplaza 'alcance' con 'contexto de ejecución' en todas partes aquí y solo entonces será correcto, ¡creo! –

1

Esto se debe a este es siempre el caso en que la función está conectada. En el caso de un EventHandler, es la clase que activó el evento.

Usted puede ayudar a su auto con una función anónima como esto:

function foo() { 
    var obj = this; 
    $("#thing").after($("<div>click me</div>").click(function(){obj.bar();})); 
} 

foo.prototype.bar = function() { 
    alert(this); 
} 
2

Usted puede utilizar Function.apply en la función para establecer lo que this debería hacer referencia a:

$("#thing").after($("<div>click me</div>").click(function() { 
    barf.apply(document); // now this refers to the document 
}); 
+1

Además de que falta un corchete cerrado en su código, la función * apply * ejecuta instantáneamente la función * barf * en lugar de devolver un puntero a la función. – Martin

+0

Gracias, ahora he corregido el puesto :) – moff

5

Hay una buena explicación sobre this palabra clave en JavaScript disponible en QuirksMode.

0
this.bar(); // when called here, "this" is the foo instance 

este comentario está mal cuando foo se utiliza como una función normal, no como un constructor. aquí:

foo();//this stands for window 
Cuestiones relacionadas