jQuery AJAX回调函数this指向问题及解决方案
本文分析jQuery AJAX回调函数中this指向jQuery配置对象而非预期实例的问题,并提供三种解决方案:使用闭包变量self、通过Function.prototype.Apply扩展方法、以及匿名函数包装调用。每种方法均包含代码示例与原理说明,帮助开发者正确处理上下文环境。
jQuery AJAX回调this指向问题分析
当在全局作用域调用包含this的对象时,当前对象的this通常指向window。为了使this的指向符合预期,JavaScript提供了call和apply两种方法来改变this指向,此外还可以利用闭包来实现。本文将通过具体示例阐述这些机制。
首先展示一段仅用于演示的代码,该代码不具备实际业务意义。
具体代码如下:
//一个没有实际意义的socket连接对象
var socket =
{
connect: function(host, port)
{
alert('Connecting socket server,host:' + host + ',port:' + port);
}
};
//一个即时通讯类,其中connect方法还将作为AJAX回调函数被调用
function classIm()
{
this.host = '192.168.1.28';
this.port = '8080';
this.connect = function(data)
{
socket.connect(this.host, this.port);
};
}
//实例化即时通讯类
var IM = new classIm();
//AJAX请求,这里假设要打开socket连接首先要通过WEB得知用户WEB登录成功
$.get('CheckWebLogin.aspx', IM.connect);
运行上述示例,你会发现弹出的host与port均为undefined。这是因为回调函数中的this并未指向IM对象,而是指向了jQuery的AJAX配置对象ajaxSettings。在jQuery内部,它使用s.success来代替传入的回调函数执行,而success的调用对象即为s,也就是下面ajaxSettings对象的缩写。
ajaxSettings:
{
url: location.href,
global: true,
type: "GET",
contentType: "application/x-www-form-urlencoded",
processData: true,
async: true
} 为了验证这一点,你可以修改代码进行测试,结果将显示url、global、type、contentType等属性名称。
具体代码如下:
this.connect = function(data)
{
for (var key in this)
{
alert(key);
}
} 解决AJAX回调this指向的三种方案
明确了问题根源后,接下来探讨解决方案。我们的目标是让AJAX回调函数代码socket.connect(this.host, this.port)中的this指向类classIm的实例对象IM,或者更准确地说,是希望socket.connect()方法能获取到正确的参数值。为了实现预期的AJAX回调执行结果,经过分析,大致有以下几种方法:
方法一
方案一:使用闭包变量self
直接传递对象的正确引用而非this指针,即对象实传。这是最常见的做法,即在类实例化时用一个变量存储对当前对象的引用,在后续方法中直接使用此变量代替this。注意:这种方法并没有真正改变this的指向。演示代码如下,请注意对比前后两次代码的区别,我也特别高亮显示了差异部分的代码。
具体代码如下:
var socket =
{
connect: function(host, port)
{
alert('Connecting socket server,host:' + host + ',port:' + port);
}
};
function classIm()
{
var self = this;
this.host = '192.168.1.28';
this.port = '8080';
this.connect = function(data)
{
socket.connect(self.host, self.port);
};
}
var IM = new classIm();
$.get('CheckWebLogin.aspx', IM.connect); 方法二
方案二:扩展Function原型使用apply
使用apply结合闭包实现真正改变this的指向。下面这种方法将函数调用时的this对象存储到一个临时变量_method,然后利用闭包将其传递给返回的function对象,在返回的function中使用apply将调用时对象的this替换为目标对象thisObj。这种方法被许多JavaScript框架采用,且下面这个Function原型方法正是我从prototype框架精简而来。注意我是先给Function原型加了Apply方法,这个Apply不是脚本内置的apply,是我自定义的,如果你喜欢可以定个别的名字。
具体代码如下:
/**
* 改变jQuery AJAX回调函数this指针指向
* @param {Object} thisObj 要替换当前this指针的对象
* @return {Function} function(data){}
*/
Function.prototype.Apply = function(thisObj)
{
var _method = this;
return function(data)
{
return _method.apply(thisObj,[data]);
};
}
var socket =
{
connect: function(host, port)
{
alert('Connecting socket server,host:' + host + ',port:' + port);
}
};
function classIm()
{
this.host = '192.168.1.28';
this.port = '8080';
this.connect = function(data)
{
socket.connect(this.host, this.port);
};
}
var IM = new classIm();
$.get('CheckWebLogin.aspx', IM.connect.Apply(IM)); 方法三
方案三:匿名函数包装调用
在匿名回调函数中再调用实际的回调处理函数。这种方法虽然可以解决同样的问题,但是代码有点长和多余,实际开发中是不建议这样做的。这种方法是保证了调用connect方法的对象还是IM对象,从而保证了this指向还是IM对象。代码如下:
具体代码如下:
$.get('CheckWebLogin.aspx', function(data){IM.connect(data)});什么时候该用JS构造器:与工厂模式、字面量的选择对比
2026-11-05 16:18:22
推荐几款轻量级JS照片墙开源库及对比
2026-11-05 15:56:19
JavaScript递归写法有哪些常见陷阱及避免方法
2026-11-05 14:53:38
JS数组浅拷贝与深拷贝怎么选?场景与方法总结
2026-11-05 14:41:02
p5.js 中 setup() 和 draw() 函数的执行机制详解
2026-11-05 12:32:38
