我正在尝试从函数中设置对象的属性:
function createObject(){
var self={};
self.foo=function(){
this.wheatly="apple";
}
return self;
}
问题是,当我调用self.foo()时,'this'指的是函数对象(self.foo),而不是父(self)。怎么能我强制该函数设置父级的属性? stackoverflow上有很多类似的问题,但作者继续使用这个'封闭'的东西,这应该适用于这里???
编辑:
我忘了提到函数是异步调用的,所以这是一个更好的例子:
http://jsfiddle.net/Pj59q/
令我困惑的是控制台(在chrome中)说this
是XMLHttpRequest(可能是在self.ajax
中声明的那个)。 this
关键字是指引用称为函数的任何对象吗?
答案 0 :(得分:1)
x = createObject()
>> Object {foo: function}
x.foo()
x
>> Object {foo: function, wheatly: "apple"}
那么,问题是什么?这是预期的行为。顺便说一句,这与闭包无关。
所以事实证明你没有提供所有必要的信息。你需要绑定你传递给ajax调用的回调,因此它知道this
应该是什么:
r.onload=this.foo.bind(this);
作为旁注,你构建createObject
的方式有点奇怪。更惯用的是:
function createObject(){
return {
foo: function() {
this.wheatly="apple";
}
};
}
答案 1 :(得分:1)
this
未引用self.foo
,而是self
。你是如何得出它引用self.foo
的结论的?您可以在控制台中验证以下情况:
var bar = createObject();
bar.wheatly; //=> undefined
bar.foo();
bar.wheatly; //=> 'apple'
因此,self
(此处标识为bar
)已被正确引用和修改。
顺便说一句,"关闭"是一个概念的名称,当在一个具有变量范围的环境中创建一个函数时,该函数会吸收("关闭")这些变量,并且即使它们外出也能继续引用它们范围。例如:
var outerFunc = function() {
var closeMe = 'hello';
return function() {
return closeMe;
};
};
innerFunc = outerFunc();
innerFunc(); //=> 'hello'
变量closeMe
已被正确读取并返回,即使它超出了范围。这是因为innerFunc
在定义时关闭了它。
我不相信你的问题(你必须为我澄清)与闭包有关。
为了确保每个人都明白为什么TGH's solution有效,请观察小提琴中的代码:
self.foo=function(){
this.wheatly="apple";
console.log(this);
}
self.ajax=function(){
var r = new XMLHttpRequest();
r.open("GET","example.com",true);
r.onload=this.foo;
r.send();
}
在此代码中,引用了self.foo
,this.foo
和r.onload
。这些引用可能有不同的名称,但它们实际上是对相同函数的引用。但是,当AJAX调用完成时,它将此函数称为r.onload
,即r
的成员。因此,this
以经典面向对象的方式指向r
。
在TGH's solution中,不使用不断变换的引用this
,而是由明确引用self
替换,该引用始终引用父对象而永远不引用{{1} }}
答案 2 :(得分:0)
function createObject(){
var self={};
self.foo=function(){
self.wheatly="apple";
}
return self;
}
上面怎么样?
答案 3 :(得分:0)
原因是当XMLHTTPRequest回调onload函数时,它会切换上下文(this)。
换句话说,XMLHTTPRequest对象实现为:
function send() {
if (status == 200) {
this.onload(); //// Now the context is XMLHTTPRequest Object!!!!
}
}
您可以将代码更改为
self.ajax=function(){
var r = new XMLHttpRequest();
r.open("GET","/",true);
var that = this;
r.onload=function() {
that.foo.apply(that);
}
r.send();
}
绑定上下文,并使用该上下文调用foo()。