2015-05-19 18 views
5

ho trovato questo codice di esempio:Come funziona "questo" nelle funzioni assegnate nel costruttore?

function personFullName() { 
    return this.first + ' ' + this.last; 
} 

function Person(first, last) { 
    this.first = first; 
    this.last = last; 
    this.fullName = personFullName; 
} 

var dude = new Person("Michael", "Jackson"); 
alert(dude.fullName()); 

che avvisa "Michael Jackson". Ho cambiato per chiamare personFullName dal costruttore invece di assegnare l'oggetto funzione:

function personFullName() { 
    return this.first + ' ' + this.last; 
} 

function Person(first, last) { 
    this.first = first; 
    this.last = last; 
    this.fullName = personFullName(); 
} 

var dude = new Person("Michael", "Jackson"); 
alert(dude.fullName); 

mi aspetterei la proprietà "fullName" di essere ormai una stringa invece di una funzione. Ma ora avvisa "indefinito indefinito". Qualcuno può spiegare perché la mia versione non funziona?

+5

Vedere questa risposta per una spiegazione completa di come 'questo' funziona: http://stackoverflow.com/questions/13441307/how-does-the-this-keyword-in-javascript-act-within-an-object -literal/13441628 # 13441628 – slebetman

risposta

6

In JavaScript, this è in genere qualsiasi cosa viene prima del . nella chiamata di funzione. Quindi il fatto che hai detto dude.fullName() è ciò che ha causato this in fullName() da impostare su dude .

Nella seconda versione della tua domanda, non la chiami allo stesso modo. Stai chiamando personFullName() senza nulla di fronte (è corretto, poiché non è più collegato a un oggetto Person). Ciò significa che this termina automaticamente con lo stesso valore di window. Poiché window non ha first o last le proprietà impostate su di esso, this.first e this.last sono undefined.

Per risolvere questo problema, è possibile rendere la vostra persona essere un argomento al personFullName() Funzione:

function personFullName(person) { 
    return person.first + ' ' + person.last; 
} 

e poi lo chiamano come

… 
this.fullName = personFullName(this); 

1: Nota che il metodo deve essere una proprietà sull'oggetto per il binding this per funzionare. Non puoi semplicemente chiamare object.someMethod() e ottenere this impostato su object in someMethod. Nel codice, il seguente non avrebbe funzionato:

function Person(first, last) { 
    this.first = first; 
    this.last = last; 
    this.fullName = this.personFullName(); 
} 

Uncaught TypeError: this.personFullName is not a function

Né sarebbe questo:

function personFullName() { 
    return this.first + ' ' + this.last; 
} 

function Person(first, last) { 
    this.first = first; 
    this.last = last; 
} 

var dude = new Person("Michael", "Jackson"); 
alert(dude.personFullName()); 

Uncaught TypeError: dude.personFullName is not a function

È possibile aggirare questa limitazione in qualsiasi situazione con la apply metodo di supporto: this.fullName = personFullName.apply(this) fa ciò che ti aspetti dalla seconda versione del tuo codice e y Puoi anche chiamare personFullName.apply(dude) in qualsiasi momento e ottenere "Michael Jackson" indietro.

1

this è la finestra della funzione personFullName in quanto non è stata chiamata nel contesto corretto. È possibile utilizzare apply per chiamarlo con il contesto corretto senza modificare la funzione personFullName.

function personFullName() { 
    return this.first + ' ' + this.last; 
} 

function Person(first, last) { 
    this.first = first; 
    this.last = last; 
    this.fullName = personFullName.apply(this); // The magic 
} 

var dude = new Person("Michael", "Jackson"); 
alert(dude.fullName); 
1

Un'alternativa migliore per risolvere questo sarebbe:

Person.prototype.personFullName = function() { 
    return this.first + ' ' + this.last; 
} 
0

Il contesto in cui ci si accedendo this nel secondo esempio, fa riferimento l'oggetto window. window non ha la proprietà fullName impostata su di esso. Se aggiungi a entrambe le funzioni vedresti cosa intendo.