john.greet("Mark")
llama en realidad una función. Cuando lo haces var fx = john.greet;
, estás obteniendo una referencia a la función. Entonces cuando lo llamas, this
no está limitado a john
. Lo que realmente está haciendo es window.fx("Mark")
y entonces this
es el objeto window
. Estabas en el camino correcto cuando dijiste que estaba en el contexto global. En esta instancia particular, el objeto global es window
, por lo que fx
es en realidad window.fx
.
Cuando tenga una función de referencia, debe usar call
o apply
si desea establecer el valor de this
. Trate de hacer esto:
fx.call(john, "Mark");
El primer argumento en call
o apply
es el valor utilizado para this
en el contexto de la llamada de función.
EDITAR
Algunas personas mencionaron que el verdadero problema aquí podría ser la confusión que rodea a un objeto literal contra una instancia de un objeto. Está creando un objeto literal que también se comporta como un singleton. No puedes crear una nueva instancia de ese objeto. En este caso, john
es una referencia a ese objeto literal. En ese contexto, this
en la función greet
se refiere a la misma literal del objeto. Por lo tanto, cuando llame al john.greet("Mark")
, this
está obligado a john
.
Cuando agarras una referencia a john.greet
sólo por sí mismo y asignarlo a una variable global, básicamente estás haciendo esto:
var fx = function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
En este escenario, es this
window
, porque fx
es básicamente window.fx
(ya que el objeto global aquí es window
. Suponiendo que este código estuviera dentro de otra función, el objeto global se referiría a esa función.
Si desea crear varias instancias de un objeto, se puede hacer algo como esto:
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"
Aquí, la variable self
(que es local a la función) mantiene una referencia a la instancia real porque eres uniéndolo al this
cuando crea el objeto.
Existen muchas mejores prácticas asociadas con OOP en Javascript. Puedes buscar y encontrar Google (hay muchos enlaces). Recomiendo leer cosas de Douglas Crockford especialmente.
La encuadernación no está "perdida"; nunca estuvo allí en primer lugar. En cualquier expresión de JavaScript 'foo.bar()', 'this' en el contexto de la función' bar() 'será' foo', independientemente de dónde se haya declarado 'bar' o cómo se asoció con' foo' '. –