2010-03-11 6 views
8

Ecco il modo standard da manuale di descrivere una 'classe' o funzione di costruzione in JavaScript, direttamente dalla Guida definitivo per JavaScript:metodi Collegamento a prototipare dall'interno funzione di costruzione

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
} 
Rectangle.prototype.area = function() { 
    return this.width * this.height; 
}; 

non lo faccio come la manipolazione del prototipo penzolante qui, quindi stavo cercando di pensare a un modo per incapsulare la definizione della funzione per area all'interno del costruttore. Sono venuto con questo, che ho fatto non si aspettano di lavorare:

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    this.constructor.prototype.area = function() { 
     return this.width * this.height; 
    }; 
} 

non mi aspettavo questo lavoro perché il riferimento this all'interno della funzione area dovrebbe puntare alla funzione area stesso, così ho non avrebbe accesso a width e height da this. Ma si scopre che lo faccio!

var rect = new Rectangle(2,3); 
var area = rect.area(); // great scott! it is 6 

Alcuni ulteriori test ha confermato che il riferimento this all'interno della funzione area realtà era un riferimento all'oggetto in costruzione, non la funzione zona stessa.

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    var me = this; 
    this.constructor.prototype.whatever = function() { 
     if (this === me) { alert ('this is not what you think');} 
    }; 
} 

scopre l'avviso si apre, e this è esattamente l'oggetto in costruzione. Allora, cosa sta succedendo qui? Perché lo this non è lo this, mi aspetto che sia?

+3

Se si dispone di un centinaio di rettangoli, si intende ridichiarlo per cento volte. Meno male che hai solo un metodo ... – kennebec

+0

Questo è un buon punto. –

risposta

5

Penso che la risposta giusta è che non si deve fare questo perché come Kennebec detto nel commento:

Se si dispone di un centinaio di rettangoli, si intenzione di ridichiarare quel metodo prototipo un centinaio di volte .

1

Ho pensato che "questo" si riferiva sempre all'oggetto contro cui era stata chiamata la funzione.

+1

Penso che la risposta ufficiale sia "dipende". –

+0

Per chiarire, 'this' fa riferimento all'oggetto attraverso il quale la funzione è stata richiamata quando la funzione viene utilizzata come metodo su un oggetto. Questo non è il caso qui. In questo caso, la funzione viene invocata come una funzione e non un metodo su un oggetto, quindi "questo" dovrebbe riferirsi realmente all'oggetto globale. –

0

A cosa punta questo, viene determinato quando viene eseguito il codice.

Ecco un modo semplice per capire che cosa dovrebbe essere questo.

Se si utilizza '.' per fare riferimento a una funzione, 'questo' sarà un riferimento a qualsiasi cosa si trovi sul lato sinistro del '.'

(Questo non tiene conto .Call e .Applicare)

var myFn = function() { 
return this.name + ' called me'; 
}; 

var me = { 
name : 'oatkiller', 
shoutOut : myFn 
}; 

var you = { 
name : 'Matthew', 
shoutOut : myFn 
}; 

// im on the left of the dot, so this points to me 
me.shoutOut(); // 'oatkiller called me' 

// youre on the left of the dot, so this points to you 
you.shoutOut(); // 'Matthew called me' 
1

Il significato di this dipende come la funzione è stata chiamata:

  • this solito si riferisce all'oggetto la funzione è chiamato da runtime, ad es quando chiamato come ob.foo(), this in foo farà riferimento a ob.
  • Se una funzione viene chiamata in un modo fornito da nessun oggetto, ad es. solo foo(), this fa riferimento alla variabile globale (l'oggetto principale che contiene tutte le altre variabili globali nel tuo programma js).
  • E in .call() e .apply(), l'oggetto a cui si riferisce this viene fornito.

Ora, se si desidera un modo per puntare all'oggetto per la funzione in cui la funzione è stata creata (ad es., il 2 ° livello this al momento della creazione), quindi si dovrebbe rinominare il più profondo this per farlo brillare attraverso quello attualmente visibile. Se questo è chiaro come il fango, questo dovrebbe aiutare a chiarire un po ':

function outside() { 
    // Here, 'this' refers to the object outside() is called with. 
    // Let's "rename" this, to make it visible to inside functions. 
    var that = this, 
     private = 42; 

    return { 
     inside: function { 
      // here, 'this' refers to the object inside() is called with, 
      // it is hiding outside's this. 
      // Also, 'that' refers to the object outside() was called with, 
      // *at the time* outside was called and inside was created. 
      // Notice that you can see 'private' 
      // (but nobody outside of 'outside()) can! 
      return private; 
     } 
    } 
} 

Questo modello di cui sopra è utile per creare l'oggetto con i metodi pubblici che possono accedere ai membri privati. Vedere Crockford per le spiegazioni probabilmente migliori.

0

Penso che tu sia molto vicino all'esempio finale. Come sull'utilizzo di un metodo privilegiato:

function Rectangle(w,h) { 
    this.width = w; 
    this.height = h; 
    var that = this; 
    this.area = function() { 
    return that.width * that.height; 
    } 
} 

var rect = new Rectangle(2,3); 
console.log(rect.area()); 

Vedi Crockford's "Private Members in JavaScript" per maggiori informazioni.

Problemi correlati