2009-05-24 93 views
5

当我通过“这个”到一个匿名函数,像这样:数据如何传递给JavaScript中的匿名函数?

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 

这里发生了什么?将变量传递给匿名函数的正确方法是什么?

对不起,这个令人困惑和冗长的帖子。

回答

5

你正在经历的是正确的行为 - 这不是一个好的行为,但它是语言的一部分。 “this”的值在内每函数定义被重置。有四种方法可以调用具有不同方式设置“this”的函数。

  1. 常规函数调用
    myFunc(param1, param2);
    这种调用函数的方式总是会将“this”重置为全局对象。这就是你的情况。
  2. 将其称为方法
    myObj.myFunc(param1, param2);
    这毫不意外地将“this”设置为该方法被调用的任何对象。在这里,“this”==“myObj”。
  3. 应用方法调用
    myFunc.apply(myObj, [param1, param2])
    这是一个很有意思的方法 - 在这里,“this”被设置为您作为apply方法的第一个参数传递的对象 - 就像在没有该方法的对象上调用方法一样该函数被写入以这种方式被调用)。所有功能默认都有apply方法。
  4. 作为构造函数(带有“new”)
    myNewObj = new MyConstructor(param1, param2);
    当您以这种方式调用函数时,“this”被初始化为一个新的对象,该对象从函数的prototype属性继承方法和属性。在这种情况下,新对象将从MyConstructor.prototype继承。另外,如果你没有明确地返回一个值,那么将返回“this”。

您使用的解决方案是推荐的解决方案 - 将“this”的外部值分配给另一个变量,该变量在您的函数中仍然可见。我唯一要改变的就是像TörökGábor所说的那样调用变量“that” - 这是事实上的标准,可能会让你的代码更容易被其他程序员阅读。

+0

很酷!非常感谢!嗯,我想我对js的工作起到了很大的舒适作用。这有点像LUA。这只是我一直在想“Java”,这并不适用。 – 0scar 2009-05-27 12:26:03

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

+0

感谢D00D!那就是:) – 0scar 2009-05-24 14:50:45

0

如果在新方法中:newRequest必须使用“for”或“while”语句,您将会遇到同样的问题。 另一种解决方案可以创建一个封闭:

这样的:

$.getJSON("answer.html",{},(function(me){return function(data){me.gotAnswer(count);}})(this)); 
相关问题