当我将'this'传递给像这样的匿名函数时:
MyClass.prototype.trigger = function(){
window.setTimeout(function(){this.onTimeout();},1000);
}
我得到“this.onTimeout不是函数” - 错误。我想在匿名函数执行时'this'不再可用了吗?所以我一直这样做:
MyClass.prototype.trigger = function(){
var me = this
window.setTimeout(function(){me.onTimeout();},1000);
}
这真的是你应该做的事情吗?它有点工作,但感觉很奇怪。
然后我们有了这个例子:
$(function(){
function MyClass(){
this.queue = new Array();
}
MyClass.prototype.gotAnswer = function(count){
$('body').append("count:"+count+"<br/>");
}
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
var me = this;
$.getJSON("answer.html",{},function(data){me.gotAnswer(count);});
}
}
var o = new MyClass();
o.queue.push(1);
o.queue.push(2);
o.loadAll();
});
输出:
2
2
不应该输出:
1
2
代替?然后我发现将$ .getJSON语句放在另一个函数中使它全部工作:
MyClass.prototype.loadAll = function(){
var count = 0;
var item;
while(item = this.queue.pop()){
count++;
this.newRequest(count);
}
}
MyClass.prototype.newRequest = function(count){
var me = this;
$.getJSON("answer.html",null,function(data){ me.gotAnswer(count); });
}
输出:
1
2
(或者相反。)这里发生了什么?将变量传递给anonnymous函数的正确方法是什么?
对于令人困惑和冗长的帖子感到抱歉。
答案 0 :(得分:5)
你所经历的是正确的行为 - 这不是一个好的行为,但它是语言的一部分。 “this”的值在每个函数定义中重置。有四种方法可以调用具有不同方法设置“this”的函数。
myFunc(param1, param2);这种调用函数的方法总是将“this”重置为全局对象。这就是你的情况。
myObj.myFunc(param1, param2);毫无疑问,将“this”设置为调用该方法的任何对象。在这里,“this”==“myObj”。
myFunc.apply(myObj, [param1, param2])这是一个有趣的方法 - 这里“this”设置为您作为apply方法的第一个参数传递的对象 - 就像在没有该方法的对象上调用方法一样方法(注意写入函数以这种方式调用)。默认情况下,所有函数都有apply方法。
myNewObj = new MyConstructor(param1, param2);当您以这种方式调用函数时,“this”被初始化为一个新对象,该对象从函数的prototype属性继承方法和属性。在这种情况下,新对象将继承自MyConstructor.prototype。此外,如果您未明确返回值,则会返回“this”。
您使用的解决方案是推荐的解决方案 - 将“this”的外部值分配给另一个在您的函数内仍然可见的变量。我唯一要改变的是将变量称为“那个”,如TörökGábor所说 - 这是事实上的标准,可能会让你的代码更容易为其他程序员阅读。
答案 1 :(得分:3)
你对闭包感到困惑。
对于第一个问题,是的,你是对的,就是这样做的方式。唯一的区别是有一个约定来命名保存that
的变量this
。
MyClass.prototype.trigger = function(){
var that = this;
window.setTimeout(function(){that.onTimeout();},1000);
}
在StackOverflow上已有一个很好的线程。检查问题 How does a javascript closure work?的答案。
您的第二个问题与Javascript closure inside loops - simple practical example完全相同。
答案 2 :(得分:0)
如果在新方法中,你将遇到同样的问题:newRequest你必须使用“for”或“while”语句。 另一个解决方案可能是创建一个闭包:
像那样:$.getJSON("answer.html",{},(function(me){return function(data){me.gotAnswer(count);}})(this));