2012-05-30 10 views
7

? He visto esto hecho mucho en JavaScript y recuerdo haber averiguado por qué, pero no recuerdo la respuesta.¿Por qué crearía una variable con valor este

supongo que es algo que ver con el alcance y la función de ser llamado fuera de la "clase", pero ¿por qué uno hacer esto (preferiblemente esbozar un ejemplo):

function myClass() 
{ 
    var self = this; 

    //... 

    this.myArray = []; 

    this.myFunc = function() { alert(self.myArray.length); }; 
} 

Respuesta

5

Con el fin de trabar sobre la variable como parte de un closure.

Por ejemplo:

MyClass.prototype.doStuff = function(){ 
    this.foundItems = []; 
    var self = this; 
    this.myString.replace(/.../,function(){ 
    // `this` is actually the `window` inside this callback 
    // so we need to use `self` to invoke another method on our instance object 
    self.foundItems.push(self.doOtherStuff()); 
    }); 
}; 

El ejemplo específico que escribió no necesita un cierre si se invoca el método de la forma esperada:

function Foo(){ 
    this.array = []; 
    this.myFunc = function(){ 
    return this.array; 
    } 
} 
var foo = new Foo; 
foo.myFunc(); // [] 

Sin embargo, es posible 'break' que como el siguiente:

var f2 = foo.myFunc; 
f2(); // undefined, since `this` was the window 

Su código usando el cierre, por otro lado, es seguro contra este tipo de t omnipresente.

+0

Así que en mi ejemplo (ahora actualizada), habría todavía necesito el '' self' antes de acceder miMatriz 'in function' myFunc'? – Cheetah

+0

Este ejemplo específico no es muy bueno, 'forEach' toma un segundo argumento que estará ligado a' this' dentro de la devolución de llamada, que debería ser preferible a la creación de la variable 'self '' hacky' '. – Esailija

+0

@Ben Depende de cómo se invoca el método. Por ejemplo: 'var o = {f: function() {return this}}; o.f() == o;/* true */var f2 = o.f; f2() == ventana;/* true */' – Phrogz

2

"esto" se refiere al "objeto" actual. El poder reside, cuando se habla de javascript, en el hecho de que la expresión "esta" se evalúa en el contexto, por lo que si un método se ejecuta en otro contexto de objeto, el valor "este" cambiará respectivamente.

1

Si crea una función dentro de otra función, this para la función interna se establece en el objeto de ventana global. Si se crea una variable de guardar el valor de this, como

var that = this; 

entonces puede utilizar that hacer referencia a la función externa dentro de la función interna.

0

Además de algunas de las respuestas publicadas por otros usuarios, la creación de una variable configurada para esto le permite reutilizar variables sin acceder a los objetos.

similar a hacer algo como:

var myElement = document.getElementById('someElement'); 

Y luego acceder a myElement si necesita más que document.getElementById varias veces.

Configuración de = this o self = esto le da acceso en todas partes a "eso" o "self" y evita que se vuelva a cargar algún objeto.

0

No creo que uno realmente quiere hacer eso:

  • Cada vez que se crea una instancia, también se crea una "copia" de la función. Entonces 5 instancias, crearán 5 "copias" de la función.
  • Esa "copia" de una función está vinculada a un entorno que solo es relevante para esa instancia específica, por lo que no se puede usar genéricamente. Eso significa que una clase que se extiende obtendrá un método que solo es relevante para alguna instancia de la clase principal que probablemente ni siquiera se use.
  • Su sangría va a salir de la mano, especialmente si comienza a anidar las funciones en línea
  • Vas a tener que cazar para funciones dentro de otras funciones en lugar de sólo mirar hacia arriba en la definición prototipo

Una alternativa :

function MyClass() { 
    this.myArray = []; 
    this.myFunc = this.myFunc.bind(this); //The "blueprint" in the prototype is not affected, the instance gets its own bound version. 
              //This means the one in prototype can be inherited or used generically anywhere else as well 
} 

MyClass.prototype = { 

    myFunc: function() { //My func is neatly listed in the prototype and can use `this` normally 
     alert(this.myArray.length); 
    }, 

    constructor: MyClass 
}; 


var myObj = new MyClass(); 

document.addEventListener("click", myObj.myFunc); //Will now work as you "expect" it to work 

algunos inconvenientes:

  • Cada función cota es una función nueva, por ejemplo, se crea una nueva función cada vez.
  • la plancha de caldera por escrito a cabo todas las llamadas .bind en el constructor, aunque puede ser mitigado con una ayuda semejante _.bindAll
Cuestiones relacionadas