2011-10-05 19 views
7
function Person(gender) { 
    this.gender = gender; 
} 

Person.prototype.sayGender = function() 
{ 
    alert(this.gender); 
}; 

var person1 = new Person('Male'); 
var genderTeller = person1.sayGender; 

person1.sayGender(); // alerts 'Male' 
genderTeller(); // alerts undefined 
 

¿Por qué genderTeller(); las alertas indefinidas no están claras para mí. si lo veo, creo que es lo mismo que la línea superior. Puede algún favor de explicar los detalles¿Por qué cambia `this` en un método al llamar una referencia al método de un objeto?

Respuesta

14

Cuando se asigna una variable como esto ...

var genderTeller = person1.sayGender; 

... se pierde el contexto del objeto person1 y this puntos de la función al objeto global (window en un navegador), en lugar del objeto instanciado person1.

Usted recibe undefined porque la propiedad gender no existe en window, y hacer referencia a una propiedad no definida en un objeto vuelve undefined en JavaScript.

Usted puede arreglar eso en los navegadores modernos con bind() ...

var genderTeller = person1.sayGender.bind(person1); 

... o jQuery tiene un método llamado también proxy().

var genderTeller = $.proxy(person1.sayGender, person1); 
+0

¿Cómo "perdemos el contexto del objeto person1" es un poco confuso. –

+0

@sushilbharwani: Como no lo llamas de inmediato, solo estás asignando una referencia a la función en una variable. Así es como funciona JavaScript. – alex

3

Está llamando a la función sin el contexto de su objeto, de modo this será el objeto global window, por lo que la función de alerta al valor de window.gender, que es undefined.

5

Así es como funciona el alcance de JavaScript. Creo que el siguiente ejemplo te dará una buena idea.

this.gender = 'Female'; 

function Person(gender) { 
    this.gender = gender; 
} 

Person.prototype.sayGender = function() 
{ 
    alert(this.gender); 
}; 

var person1 = new Person('Male'); 
var genderTeller = person1.sayGender; 

person1.sayGender(); // alerts 'Male' 
genderTeller(); // alerts 'Female' 

No es una forma sencilla de averiguar cuál es el valor de this en una función que está llamando. Suele ser el object antes del dot donde invocó la función. Por ejemplo:

person1.sayGender() aquí this = person1

object1.object2.foo() aquí this = object2

genderTeller() aquí this = window, porque no se está llamando desde cualquier objeto.

Obviamente se puede establecer el valor de this con .call o .apply función, pero por lo general seguir a esta regla cuando construyo un modelo mental de mi código.

Cuestiones relacionadas