2012-05-30 13 views
7

Ho visto questo fatto molto in JavaScript e ricordo di aver scoperto perché, ma non riesco a ricordare la risposta.Perché dovresti creare una variabile con valore questo

Sto indovinando è qualcosa a che fare con il campo di applicazione e una funzione di essere chiamato fuori dalla "classe", ma perché uno dovrebbe fare questo (preferibilmente che delinea un esempio):

function myClass() 
{ 
    var self = this; 

    //... 

    this.myArray = []; 

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

risposta

5

Al fine di agganciare la variabile come parte di un closure.

Ad esempio:

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()); 
    }); 
}; 

L'esempio specifico che hai scritto non ha bisogno di una chiusura, se si richiama il metodo nel modo previsto:

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

Tuttavia, è possibile 'break' è così:

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

Il tuo codice utilizzando la chiusura, d'altra parte, è sicuro contro questo tipo di t omfoolery.

+0

Così, nel mio esempio (ora aggiornato), avrei ancora bisogno del 'self' prima di accedere' myArray 'in funzione' myFunc'? – Cheetah

+0

Questo esempio specifico non è molto buono, 'forEach' prende un secondo argomento che sarà associato a' this' all'interno del callback, che dovrebbe essere preferito rispetto alla creazione della variabile "self" "hacky". – Esailija

+0

@Ben Dipende da come viene invocato il metodo. Ad esempio: 'var o = {f: function() {return this}}; o.f() == o;/* true */var f2 = o.f; f2() == finestra;/* true */' – Phrogz

2

"questo" si riferisce all'attuale "oggetto". Il potere risiede, quando si parla di javascript, nel fatto che l'espressione "questo" viene valutata in base al contesto, così ad esempio se un metodo viene eseguito in un altro contesto oggetto, il valore "questo" cambierà rispettivamente.

1

Se si crea una funzione all'interno di un'altra funzione, this per la funzione interna viene impostata sull'oggetto della finestra globale. Se si crea una variabile salvare il valore di this, come

var that = this; 

quindi è possibile utilizzare that fare riferimento alla funzione esterna all'interno della funzione interna.

0

In aggiunta ad alcune delle risposte pubblicate da altri utenti, la creazione di un set di variabili consente di riutilizzare le variabili senza accedere agli oggetti.

Simile a fare qualcosa di simile:

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

E poi l'accesso ai MyElement se è necessario, piuttosto che document.getElementById più volte.

Impostazione che = this o self = questo consente di accedere ovunque a "that" o "self" e impedisce di ricaricare alcuni oggetti.

0

Non credo che si vuole davvero farlo:

  • Ogni volta che viene creata un'istanza, si crea anche una "copia" della funzione. Quindi 5 istanze creeranno 5 "copie" della funzione.
  • Quella "copia" di una funzione è legata a un ambiente che è rilevante solo per quella specifica istanza, quindi non può essere utilizzato genericamente. Ciò significa che una classe estesa otterrà un metodo che è rilevante solo per alcune istanze della classe genitore che probabilmente non viene nemmeno utilizzata.
  • tuo rientro sarà sfuggire di mano, soprattutto se si inizia la nidificazione quelle funzioni inline
  • Dovrete andare a caccia di funzioni all'interno di altre funzioni invece di guardare in su nella definizione del prototipo

Un'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 

alcuni inconvenienti:

  • Ogni funzione limite è una nuova funzione quindi, ad esempio, ogni volta viene creata una nuova funzione.
  • Boilerplate per iscritto tutte le chiamate .bind nel costruttore, anche se può essere mitigato con un aiutante come _.bindAll
Problemi correlati