john.greet("Mark")
chiama in realtà una funzione. Quando si esegue var fx = john.greet;
, si ottiene un riferimento alla funzione. Quindi quando lo chiami, this
non è legato a john
. Quello che stai facendo in realtà è window.fx("Mark")
e quindi this
è l'oggetto window
. Eri sulla strada giusta quando hai detto che era nel contesto globale. In questa particolare istanza, l'oggetto globale è window
e quindi fx
è in realtà window.fx
.
Se si dispone di un riferimento di funzione, è necessario utilizzare call
o apply
se si desidera impostare il valore di this
. Prova a fare questo:
fx.call(john, "Mark");
Il primo argomento in call
o apply
è il valore utilizzato per this
nel contesto della chiamata di funzione.
EDIT
Alcune persone detto che il vero problema qui potrebbe essere confusione che circonda un oggetto letterale contro un'istanza di un oggetto. Stai creando un oggetto letterale che si comporta anche come un singleton. Non è possibile creare una nuova istanza di quell'oggetto. In questo caso, john
è un riferimento a tale oggetto letterale. In questo contesto, this
nella funzione greet
fa riferimento all'oggetto letterale stesso. Quindi quando si chiama john.greet("Mark")
, this
è legato a john
.
quando si impugna un riferimento a john.greet
basta da solo e di assegnarlo a una variabile globale, si sta essenzialmente facendo questo:
var fx = function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
In questo scenario, è this
window
, perché fx
è fondamentalmente window.fx
(Poiché l'oggetto globale è window
. Supponendo che questo codice sia stato incluso all'interno di un'altra funzione, l'oggetto globale farebbe riferimento a tale funzione.
Se si desidera creare più istanze di un oggetto, si può fare qualcosa di simile:
var Person = function(name) {
var self = this; //maintains a reference to the instance
this.name = name;
this.greet = function(name) {
alert("Hi " + name + ", my name is " + self.name);
}
}
var john = new Person("John");
john.greet("Mark"); // alerts "Hi Mark, my name is John"
var fx = john.greet;
fx("Mark"); // also alerts "Hi Mark, my name is John"
Qui, la variabile self
(che è locale alla funzione) mantiene un riferimento all'istanza reale perché sei legandolo a this
quando si crea l'oggetto.
Esistono molte best practice associate a OOP in Javascript. Puoi Google e scoprire (ci sono molti link). Consiglio soprattutto di leggere roba da Douglas Crockford.
Il binding non è "perso" - non è mai stato lì in primo luogo. In qualsiasi espressione JavaScript 'foo.bar()', 'this' nel contesto della funzione' bar() 'sarà' foo', indipendentemente da dove è stato dichiarato 'bar' o da come è stato associato a' foo '. –