john.greet("Mark")
实际上调用了一个函数。当您这样做时var fx = john.greet;
,您将获得对该函数的引用。因此,当您调用它时,this
不会绑定到john
. 你实际上做的是window.fx("Mark")
等this
为window
对象。当你说它是在全球范围内时,你是在正确的轨道上。在这个特定的例子中,全局对象是window
,fx
实际上也是window.fx
。
当你有一个函数引用时,你应该使用call
或者apply
如果你想设置this
. 尝试这样做:
fx.call(john, "Mark");
call
or 中的第一个参数apply
是this
函数调用上下文中使用的值。
编辑
有些人提到这里的真正问题可能是围绕对象文字与对象实例的混淆。您正在创建一个对象文字,它的行为也有点像单例。您不能创建该对象的新实例。在这种情况下john
是对该对象文字的引用。在那种情况下,this
在函数greet
中指的是对象文字本身。因此,当您调用 时john.greet("Mark")
,this
必然会john
.
当您仅获取对john.greet
自身的引用并将其分配给全局变量时,您实际上是在执行以下操作:
var fx = function(person) {
alert("Hi " + person + ", my name is " + this.name);
}
在这种情况下,this
is window
,因为fx
基本上是window.fx
(因为这里的全局对象是window
。假设这段代码被包装在另一个函数中,那么全局对象将引用该函数。
如果你想创建一个对象的多个实例,你可以这样做:
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"
在这里,self
变量(函数的局部变量)维护对实际实例的引用,因为您在this
创建对象时将其绑定到。
在 Javascript 中有许多与 OOP 相关的最佳实践。你可以谷歌搜索一下(有很多链接)。我特别推荐阅读 Douglas Crockford 的文章。