2011-01-15 17 views
27

Básicamente tengo un objeto, ampliado con una función a través de su prototipo. Dentro de esa función, existe otra función; sin embargo, al usar this en esta función anidada, no parece referirse al objeto, sino a la función.'this' en función dentro de la función de prototipo

Por ejemplo,

var sampleObject = function() { 
this.foo = 123; 
} 

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
} 
return nested(); 
} 

var test = new sampleObject(); 

window.alert(test.getFoo()); // undefined 

El this.foo no se refiere al valor de 123, pero no está definida como esto se refiere a la función anidada, en la que no existe foo. ¿Cómo puedo acceder al valor 123 desde la función anidada?

Gracias.

+1

posible duplicado de [En Javascript, ¿por qué el operador "this" es incoherente?] (Http://stackoverflow.com/questions/80084/in-javascript-why-is-the-this-operator-inconsistent) –

Respuesta

30
sampleObject.prototype.getFoo = function() { 
var me = this; 
var nested = function() { 
    return me.foo; 
} 
return nested; 
} 

Al guardar el valor de this en una variable local, que hacen que sea explícitamente parte del contexto léxico para esa función y para todos los ámbitos de funciones anidadas. Por lo tanto, en la llamada a "anidado", esa función interna tendrá su propio alcance (es su propio valor this), pero aún puede hacer referencia a la variable "yo" en el ámbito adjunto.

+0

y qué pasará si lo hago: 'var foo = new sampleObject();' '$ (ventana) .on ('scroll', foo.getFoo);' – vsync

+0

@vsync que debería estar bien - si usted ' Si tiene problemas con algo así, le sugiero que abra una nueva pregunta con la muestra del código que está causando dificultades. – Pointy

+1

pero eso no está bien, porque al usar una referencia de función perdemos el 'this' que es tan vital para el prototipado, entonces' var me = this; 'en su ejemplo apuntará al objeto' window' – vsync

8

El trabajo común en torno a esto es utilizar el cierre

sampleObject.prototype.getFoo = function() { 
    var _this = this; 
    var nested = function() { 
    return _this.foo; 
    } 
    return nested(); 
} 

Algunas bibliotecas agregan métodos para automatizar este

+1

Prefiero el modo no automatizado, ya que no es tan complejo, gracias – pimvdb

+1

Puede preferirlo en esta situación, pero la forma automatizada es realmente agradable para los controladores de eventos. – Hemlock

0

Esta es una verruga conocida en JavaScript. El patrón habitual es asignarlo a otra variable (a menudo uno mismo) en la función externa, luego acceda a sí mismo desde la función interna. Esto funciona.

3

Además de declararlo a var _this = this, también veo códigos que hacen var that = this o var self = this.

Conocer el alcance de su variable es importante ya que podría generar un resultado inesperado.

+0

si está haciendo un proyecto grande con una convención. es decir, siempre use var que = this; o uno mismo o lo que sea –

+0

Para mí, 'that' es generalmente la variable en una función de prototipo, p. 'foo.prototype.add = function (that) {return this + that}', entonces prefiero 'self' o' me'. – pimvdb

1

Esta es una vieja pregunta, pero le doy otra solución por el bien de la integridad. Otro enfoque implica function binding.

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
} 
return nested.bind(this)(); 
} 
+0

hey, esto es genial ... entonces ... ¿puedes elaborar mostrando una función con un parámetro? Tengo la sensación de que se ve similar, pero ... diferente – bkwdesign

4

En su ejemplo "este" se refiere al objeto de ventana, porque no se ha especificado otro contexto cuando se llama a la función anidada y se obtiene undefind porque window.foo no está definido.

Puede solucionar esto de 3 maneras.

1 - Utilizar una variable para almacenar el fuera de esta - método más utilizado

sampleObject.prototype.getFoo = function() { 
var _this = this; 
var nested = function() { 
    return _this.foo; 
} 
return nested(); 
} 

2 - Utilizar el método de enlace que se unen el exterior "this" a la interior

sampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
}.bind(this); 
return nested(); 
} 

3 - Utilizar el método de llamada que puede pasar el contexto de la función

SampleObject.prototype.getFoo = function() { 
var nested = function() { 
    return this.foo; 
}; 
return nested.call(this); 
} 
0

tl; dr

Use arrow functions. Están disponibles desde ECMAScript 6:

var sampleObject = function() { 
 
    this.foo = 123; 
 
} 
 

 
sampleObject.prototype.getFoo = function() { 
 
    var nested =() => { // Changed this line. 
 
    return this.foo; 
 
    } 
 
    return nested(); 
 
} 
 

 
var test = new sampleObject(); 
 

 
window.alert(test.getFoo());

Explicación

Ésta es una de las principales ventajas de las funciones de dirección. Su caso se describe en la sección: No binding of this. Los estados refference:

Hasta las funciones de dirección, cada nueva función definida por su propio valor this [...] Una función de flecha no crea su propio contexto this, por lo this tiene el significado original del contexto circundante.

Cuestiones relacionadas