2011-01-15 17 views
27

Fondamentalmente ho un oggetto, esteso con una funzione attraverso il suo prototipo. All'interno di questa funzione esiste un'altra funzione, tuttavia quando si utilizza this in questa funzione annidata, non sembra riferirsi all'oggetto, ma alla funzione.'questo' in funzione all'interno della funzione prototipo

Ad esempio,

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 

Il this.foo non si riferisce al valore 123, ma non è definito come questo si riferisce alla funzione nidificata, in cui non esiste foo. Come posso accedere al valore 123 dalla funzione annidata?

Grazie.

+1

possibile duplicato di [In Javascript, perché l'operatore "questo" è incoerente?] (Http://stackoverflow.com/questions/80084/in-javascript-why-is-the-this-operator-inconsistent –

risposta

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

Salvando il valore di this in una variabile locale, si fanno esplicitamente parte del contesto lessicale per quella funzione e per tutti gli ambiti di funzioni annidate. Quindi, nella chiamata a "annidato", quella funzione interna avrà il proprio ambito (è il proprio valore this), ma può ancora fare riferimento alla variabile "me" nell'ambito di inclusione.

+0

e cosa succede se faccio: 'var foo = new sampleObject();' '$ (finestra) .on ('scroll', foo.getFoo);' – vsync

+0

@vsync che dovrebbe andare bene - se tu ' Se avessi problemi con qualcosa del genere, ti suggerisco di aprire una nuova domanda con l'esempio di codice che causa difficoltà. – Pointy

+1

ma non va bene, perché usando un riferimento a una funzione perdiamo il 'this' che è così vitale per la prototipazione, quindi' var me = this; 'nel tuo esempio punta all'oggetto' window' – vsync

8

Il lavoro comune intorno per che è quello di utilizzare la chiusura

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

Alcune librerie aggiungono metodi per automatizzare questo

+1

Preferisco il modo non automatizzato in quanto non è così complesso, grazie – pimvdb

+1

Si può preferire in questa situazione, ma il modo automatico è davvero piacevole per i gestori di eventi. – Hemlock

0

Questa è una verruca nota su JavaScript. Il solito schema è di assegnare questo a un'altra variabile (spesso auto) nella funzione esterna, quindi accedere al sé dalla funtction interiore. Questo funziona.

3

Oltre a dichiararlo a var _this = this, vedo anche codici che fanno var that = this o var self = this.

La conoscenza dell'ambito della variabile è importante in quanto potrebbe generare risultati imprevisti.

+0

se stai facendo un progetto di grandi dimensioni con una convenzione. cioè usa sempre var that = this; o auto o cosa mai –

+0

Per me, 'that' è di solito la variabile in una funzione prototipo, ad es. 'foo.prototype.add = function (that) {return this + that}', quindi preferisco 'self' o' me'. – pimvdb

1

Questa è una vecchia domanda, ma fornisco un'altra soluzione per motivi di completezza. Un altro approccio riguarda lo function binding.

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

hey, questo è bello .. quindi .. puoi elaborare mostrando una funzione con un parametro .. Ho la sensazione che sembri simile, ma .. diverso – bkwdesign

4

Nel tuo esempio "questo" si riferisce all'oggetto finestra, perché non è stato specificato un altro contesto, quando si chiama la funzione nidificato e si ottiene undefind perché window.foo non è definito.

È possibile risolvere questo problema in 3 modi.

1 - Utilizzare una variabile per memorizzare l'esterno questo - metodo più utilizzato

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

2 - Utilizzare il metodo bind che vincolano l'esterno "questo" per quella interna

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

3 - Utilizzare il metodo di chiamata che può passare contesto alla funzione

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

tl; dr

Utilizzare arrow functions. Sono disponibili dal 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());

Spiegazione

Questo è uno dei vantaggi principali di funzioni di direzione. Il tuo caso è descritto nella sezione: No binding of this. Gli stati di riferimento:

Fino funzioni di direzione, ogni nuova funzione definita proprio this valore [...] Una funzione freccia non crea una propria this contesto, in modo da this ha il significato originale dal contesto che racchiude.

Problemi correlati