避免丢失此引用以及为什么会发生这种情况

时间:2011-11-16 16:01:50

标签: javascript callback this module-pattern

我有这个小提琴有错误 - > http://jsfiddle.net/Osoascam/AkZZr/6/ (这是没有错误的版本) - > http://jsfiddle.net/Osoascam/AkZZr/7/

其中有一个模块(如主应用程序),一个处理Ajax调用的Module.AjaxInterface,一个Module.Modules.Inbox(执行与电子邮件收件箱相关的任务)和一个{{1它处理几个显示页面的模块。所有这些都是使用模块模式完成的。

现在,您可以看到有很多回调。我想知道这些电话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() r我有这个:

pretendRende

我的问题是...... 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?我该如何解决?我知道我可以使用windowcall,但apply上的pretendRender函数被调用,AjaxInterface的引用已丢失(除非我使用Modules.Inbox,我不能在caller下。我知道我可以将"strict"传递给this以保留它,但我真正想要的是真正了解正在发生的事情并创建一个优雅的解决方案。

2 个答案:

答案 0 :(得分:4)

this.pretendRender只是函数的引用/指针,调用函数时this的上下文取决于很多东西:

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

this将在bc,因为c引用的函数被称为b的属性


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

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


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

this将是this内的c,无论是什么因为c引用的函数是一个绑定函数,它调用原始函数并将上下文设置为原this.bind存在于现代浏览器中,但must be included to be sure可用。


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

this将在someObjectc,因为它是明确给出的。


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

jsfiddle

答案 1 :(得分:2)

this始终是调用函数的对象。它改变。 this.pretendRender不是在该时间点附加到this对象的方法。这只是一个被传递的功能。如果您想保证该上下文中的this随该方法移动,则需要绑定 this到该函数。像这样(使用闭包):

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

使用_.bind()下划线.js框架有一个更好的方法。