当前位置: 首页 > 图文教程 > 网络编程 > Javascript > jQuery AJAX回调函数this指向问题

Javascript
JS暴虐查找法简洁版
JavaScript数组问题解决的多种方法
比较炫的图片播放器 js 焦点效果代码
js iframe网站后台左右收缩型页面脚本
javascript完美随机广告代码
北京奥运会倒计时代码
javascript 数据结构的题
js停止输出代码
兼容多浏览器的字幕特效Marquee的通用js类
IE8 引入跨站数据获取功能说明
javascript 支持ie和firefox杰奇翻页函数
js添加删除行和双击变文本框的脚本
JavaScript 版本自动生成文章摘要
用js遍历 table的脚本
用JavaScript实现UrlEncode和UrlDecode的脚本代码
css把超出的部分显示为省略号的方法兼容火狐
javascript IE中的DOM ready应用技巧
js退弹 IE关闭时弹出广告代码,可以防止屏蔽
js类中的公有变量和私有变量
兼容firefox的给每一个onClick再附加一个事件

Javascript 中的 jQuery AJAX回调函数this指向问题


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2010-02-27   浏览: 438 ::
收藏到网摘: n/a

了解JavaScript的人都知道JavaScript的this不总是指向当前对象,函数或类中的this指向与调用这个函数的对象以及上下文环境是息息相关的。 如在全局作用域调用一个含this的对象,此时当前对象的this指向的是window。为了让this的指向符合自己的意愿,JavaScript提供了两个方法用以改变this的指向,它们是call和apply,当然也有利用闭包来实现的方法。本文通过一个例子来说明这些问题。
先看一段演示代码,这代码只供演示用,没有实际意义。
复制代码 代码如下:

//一个没有实际意义的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回调函数代码socket.connect(this.host, this.port)中的this指向类classIm的实例对象IM,或者说是想socket.connect()方法能得到正确的参数值吧。为了得到预期的AJAX回调函数执行结果,我分析了大致有下面几种方法:
方法一

直接传对象的正确引用而非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);

方法二
使用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)});