2011-11-16 78 views
0

我有这个拨弄它有一个错误 - > (这是没有错误的版本) - >http://jsfiddle.net/Osoascam/AkZZr/7/避免失去这个参考和使用它的原因

在这里面,有一个模块(如主要应用程序),处理Ajax调用的Module.AjaxInterface,执行与电子邮件收件箱相关的任务的Module.Modules.Inbox以及处理若干模块以显示页面的Module.Pages.Gmail。所有这些都是使用模块模式完成的。

现在,你可以看到有很多回调。我想知道发生了什么this上的呼叫:

我不明白的是发生了什么this参考,我该如何维护它:

getMessages: function(params) { 
       var parameters = params || {}; 
       params = { 
        // Please note I'm using this, which equals the module 
        successCallback: this.pretendRender, 
        successCallbackParameters: parameters, 
        json: params.json 
       }; 
       var test = new Module.AjaxInterface(params); 
       test.ajaxCall(); 
      }, 

因此,调用模块内部的函数本身工作...然后,它调用test.ajaxCalls,该函数返回调用pretendRender()。现在,pretendRende R I有这样的:

pretendRender: function(data, parameters) { 
       // LINE 106 that is causing the ERROR 
       // It says "this.addColor() is not defined and THIS = window now 
       data.color = this.addColor(); 
       parameters.successCallback(data); 
      }, 

      addColor: function() { 
       return "#AD9"; 
      } 

我的问题是...什么是发生在this参考?为什么会更改为window?我该如何解决它?我知道我可以使用callapply,但函数pretendRenderAjaxInterface上被调用,并且对Modules.Inbox的引用已经丢失(除非我使用caller,我不能在"strict"下)。我知道我可以通过thisAjaxInterface来保存它,但我真正想要的是真正理解正在发生的事情并创建一个优雅的解决方案。

回答

4

this.pretendRender只是一个参考/指向函数的指针,当函数被调用的this上下文取决于很多事情:

a.b.c = this.pretendRender; 
a.b.c(); 

thisbc因为函数由c引用正在被称为的b


window.a = this.pretendRender; 
a(); 
属性

this将被设置为global object因为a引用的函数被称为的global object


a.b.c = this.pretendRender.bind(this); 
a.b.c(); 

this属性将原来thisc不管是什么,因为功能的引用c是一个绑定函数,它将上下文设置为原始的this,调用原始函数。 .bind存在于现代浏览器中,但must be included to be sure可用。


a.b.c = this.pretendRender; 
a.b.c.call(someObject); 

thissomeObject里面c,因为它明确给出。


由于您使用jQuery,而不是this.pretendRender.bind(this);可以使用successCallback: $.proxy(this.pretendRender, this)

jsfiddle

+0

嗯......我明白了......这不是我想要“这个”在回调中......我只需要一种方法来调用addColor()...并且它说它是未定义的,如果我只是将其保留为 –

+0

您调用'this.addColor()',它将在'this'设置正确时起作用。所以:'successCallback:$ .proxy(this.pretendRender,this)'如果你使用的是jQuery是你需要改变的唯一东西,它应该工作..请看这里http://jsfiddle.net/AkZZr/8/。我这样做只是改变,它开始工作。 – Esailija

+0

完美!非常感谢你! –

2

this始终是函数被调用的对象。它改变。 this.pretendRender不是在该时间点附加到this对象的方法。这只是一个正在传递的函数。如果你想保证在这种情况下this与该方法一起旅行,你需要绑定this该功能。这样的事情(使用闭包):

var me = this; 
params = { 
    successCallback: function() { return me.pretendRender.apply(me, arguments); }, 
    ... 
} 

的underscore.js框架与_.bind()这样做的相当好的方式。

+0

谢谢你的解释... 但我做successCallback:'this.pretendRender', (即将引用传递给该函数,而不是调用函数本身)。如果我这样做'me.pretendRender.apply(me,arguments);',我不会调用函数吗? 此外,该函数的参数应用于'Module.AjaxInterface'并且该函数在那里执行,在'callback(data,parameters)中调用其引用;' 这就是为什么我不知道如何使用应用,因为函数引用被传递,然后在另一个模块中执行。 –

+0

它会被调用,如果不是'function(){...}'包装呼叫。这会创建一个匿名函数,稍后会调用这个函数,将'this'引用保存在'me'变量中。 – dlamotte

+0

好吧,我试过'successCallback:function(data){return me.pretendRender.call(me,data);',它返回'addColor没有定义'。 (在这个js小提琴 - > http://jsfiddle.net/Osoascam/AkZZr/9/) –