jQuery AJAX回調(diào)函數(shù)this指向問(wèn)題
更新時(shí)間:2010年02月08日 07:19:19 作者:
了解JavaScript的人都知道JavaScript的this不總是指向當(dāng)前對(duì)象,函數(shù)或類(lèi)中的this指向與調(diào)用這個(gè)函數(shù)的對(duì)象以及上下文環(huán)境是息息相關(guān)的。
如在全局作用域調(diào)用一個(gè)含this的對(duì)象,此時(shí)當(dāng)前對(duì)象的this指向的是window。為了讓this的指向符合自己的意愿,JavaScript提供了兩個(gè)方法用以改變this的指向,它們是call和apply,當(dāng)然也有利用閉包來(lái)實(shí)現(xiàn)的方法。本文通過(guò)一個(gè)例子來(lái)說(shuō)明這些問(wèn)題。
先看一段演示代碼,這代碼只供演示用,沒(méi)有實(shí)際意義。
//一個(gè)沒(méi)有實(shí)際意義的socket連接對(duì)象
var socket =
{
connect: function(host, port)
{
alert('Connecting socket server,host:' + host + ',port:' + port);
}
};
//一個(gè)即時(shí)通訊類(lèi),其中connect方法還將作為AJAX回調(diào)函數(shù)被調(diào)用
function classIm()
{
this.host = '192.168.1.28';
this.port = '8080';
this.connect = function(data)
{
socket.connect(this.host, this.port);
};
}
//實(shí)例化即時(shí)通訊類(lèi)
var IM = new classIm();
//AJAX請(qǐng)求,這里假設(shè)要打開(kāi)socket連接首先要通過(guò)WEB得知用戶(hù)WEB登錄成功
$.get('CheckWebLogin.aspx', IM.connect);
運(yùn)行上面的例子,你將看到彈出的host與port都是undefined,那是因?yàn)榛卣{(diào)函數(shù)的this不是指向IM對(duì)象,而是jQuery的AJAX配置對(duì)象ajaxSettings。在jQuery內(nèi)部是用s.success代替?zhèn)魅氲幕卣{(diào)函數(shù)去執(zhí)行的,而success的調(diào)用對(duì)象就是s,即下面ajaxSettings對(duì)象的縮寫(xiě)。
ajaxSettings:
{
url: location.href,
global: true,
type: "GET",
contentType: "application/x-www-form-urlencoded",
processData: true,
async: true
}
為了證明這一點(diǎn),你可以這樣修改代碼測(cè)試一下,你將看到是url、global、type、contentType等對(duì)象的屬性名稱(chēng):
this.connect = function(data)
{
for (var key in this)
{
alert(key);
}
}
現(xiàn)在了解了問(wèn)題所在,接下來(lái)想辦法解決這個(gè)問(wèn)題。其實(shí)我們的目的是希望AJAX回調(diào)函數(shù)代碼socket.connect(this.host, this.port)中的this指向類(lèi)classIm的實(shí)例對(duì)象IM,或者說(shuō)是想socket.connect()方法能得到正確的參數(shù)值吧。為了得到預(yù)期的AJAX回調(diào)函數(shù)執(zhí)行結(jié)果,我分析了大致有下面幾種方法:
方法一
直接傳對(duì)象的正確引用而非this指針,或叫對(duì)象實(shí)傳。這是最常見(jiàn)的做法,即在類(lèi)實(shí)例化時(shí)用一個(gè)變量存儲(chǔ)對(duì)當(dāng)前對(duì)象的引用,在后面的方法中直接使用此變量代替this的使用。注意:這種方法并沒(méi)有真正改變this的指向。演示代碼如下,注意對(duì)比前后兩次代碼的區(qū)別,我也特別高亮顯示差異部分代碼。
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加閉包實(shí)現(xiàn)真正改變this的指向。下面方法把函數(shù)調(diào)用時(shí)的this對(duì)象存到一個(gè)臨時(shí)變量_method,然后又利用閉包把它傳給返回的function對(duì)象,在這個(gè)返回的function中使用apply把調(diào)用時(shí)對(duì)象的this替換為目標(biāo)對(duì)象thisObj。這種方法是很多JavaScript框架的做法,而且下面這個(gè)Function原型方法正是我從prototype框架精簡(jiǎn)而來(lái)。注意我是先給Function原型加了Apply方法,這個(gè)Apply不是腳本內(nèi)置的apply,是我自定義的,如果你喜歡可以定個(gè)別的名字。
/**
* 改變jQuery AJAX回調(diào)函數(shù)this指針指向
* @param {Object} thisObj 要替換當(dāng)前this指針的對(duì)象
* @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));
方法三
在匿名回調(diào)函數(shù)中再調(diào)用實(shí)際的回調(diào)處理函數(shù)。這種方法雖然可以解決同樣的問(wèn)題的,但是代碼有點(diǎn)長(zhǎng)和多余,實(shí)際開(kāi)發(fā)中是不建議這樣做的。這種方法是保證了調(diào)用connect方法的對(duì)象還是IM對(duì)象,從而保證了this指向還是IM對(duì)象。代碼如下:
$.get('CheckWebLogin.aspx', function(data){IM.connect(data)});
先看一段演示代碼,這代碼只供演示用,沒(méi)有實(shí)際意義。
復(fù)制代碼 代碼如下:
//一個(gè)沒(méi)有實(shí)際意義的socket連接對(duì)象
var socket =
{
connect: function(host, port)
{
alert('Connecting socket server,host:' + host + ',port:' + port);
}
};
//一個(gè)即時(shí)通訊類(lèi),其中connect方法還將作為AJAX回調(diào)函數(shù)被調(diào)用
function classIm()
{
this.host = '192.168.1.28';
this.port = '8080';
this.connect = function(data)
{
socket.connect(this.host, this.port);
};
}
//實(shí)例化即時(shí)通訊類(lèi)
var IM = new classIm();
//AJAX請(qǐng)求,這里假設(shè)要打開(kāi)socket連接首先要通過(guò)WEB得知用戶(hù)WEB登錄成功
$.get('CheckWebLogin.aspx', IM.connect);
運(yùn)行上面的例子,你將看到彈出的host與port都是undefined,那是因?yàn)榛卣{(diào)函數(shù)的this不是指向IM對(duì)象,而是jQuery的AJAX配置對(duì)象ajaxSettings。在jQuery內(nèi)部是用s.success代替?zhèn)魅氲幕卣{(diào)函數(shù)去執(zhí)行的,而success的調(diào)用對(duì)象就是s,即下面ajaxSettings對(duì)象的縮寫(xiě)。
ajaxSettings:
{
url: location.href,
global: true,
type: "GET",
contentType: "application/x-www-form-urlencoded",
processData: true,
async: true
}
為了證明這一點(diǎn),你可以這樣修改代碼測(cè)試一下,你將看到是url、global、type、contentType等對(duì)象的屬性名稱(chēng):
復(fù)制代碼 代碼如下:
this.connect = function(data)
{
for (var key in this)
{
alert(key);
}
}
現(xiàn)在了解了問(wèn)題所在,接下來(lái)想辦法解決這個(gè)問(wèn)題。其實(shí)我們的目的是希望AJAX回調(diào)函數(shù)代碼socket.connect(this.host, this.port)中的this指向類(lèi)classIm的實(shí)例對(duì)象IM,或者說(shuō)是想socket.connect()方法能得到正確的參數(shù)值吧。為了得到預(yù)期的AJAX回調(diào)函數(shù)執(zhí)行結(jié)果,我分析了大致有下面幾種方法:
方法一
直接傳對(duì)象的正確引用而非this指針,或叫對(duì)象實(shí)傳。這是最常見(jiàn)的做法,即在類(lèi)實(shí)例化時(shí)用一個(gè)變量存儲(chǔ)對(duì)當(dāng)前對(duì)象的引用,在后面的方法中直接使用此變量代替this的使用。注意:這種方法并沒(méi)有真正改變this的指向。演示代碼如下,注意對(duì)比前后兩次代碼的區(qū)別,我也特別高亮顯示差異部分代碼。
復(fù)制代碼 代碼如下:
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加閉包實(shí)現(xiàn)真正改變this的指向。下面方法把函數(shù)調(diào)用時(shí)的this對(duì)象存到一個(gè)臨時(shí)變量_method,然后又利用閉包把它傳給返回的function對(duì)象,在這個(gè)返回的function中使用apply把調(diào)用時(shí)對(duì)象的this替換為目標(biāo)對(duì)象thisObj。這種方法是很多JavaScript框架的做法,而且下面這個(gè)Function原型方法正是我從prototype框架精簡(jiǎn)而來(lái)。注意我是先給Function原型加了Apply方法,這個(gè)Apply不是腳本內(nèi)置的apply,是我自定義的,如果你喜歡可以定個(gè)別的名字。
復(fù)制代碼 代碼如下:
/**
* 改變jQuery AJAX回調(diào)函數(shù)this指針指向
* @param {Object} thisObj 要替換當(dāng)前this指針的對(duì)象
* @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));
方法三
在匿名回調(diào)函數(shù)中再調(diào)用實(shí)際的回調(diào)處理函數(shù)。這種方法雖然可以解決同樣的問(wèn)題的,但是代碼有點(diǎn)長(zhǎng)和多余,實(shí)際開(kāi)發(fā)中是不建議這樣做的。這種方法是保證了調(diào)用connect方法的對(duì)象還是IM對(duì)象,從而保證了this指向還是IM對(duì)象。代碼如下:
復(fù)制代碼 代碼如下:
$.get('CheckWebLogin.aspx', function(data){IM.connect(data)});
您可能感興趣的文章:
- jQuery 選擇方法及$(this)用法實(shí)例分析
- 淺談jQuery this和$(this)的區(qū)別及獲取$(this)子元素對(duì)象的方法
- jQuery中$this和$(this)的區(qū)別介紹(一看就懂)
- 實(shí)例講解JQuery中this和$(this)區(qū)別
- 詳談jQuery中的this和$(this)
- 通過(guò)$(this)使用jQuery包裝后的方法或?qū)傩?/a>
- jquery $(this).attr $(this).val方法使用介紹
- jquery中this的使用說(shuō)明
- JQuery this 和 $(this) 的區(qū)別
- JQuery中this的指向詳解
相關(guān)文章
深入了解JavaScript中的二進(jìn)制操作及位掩碼應(yīng)用
在JavaScript中,二進(jìn)制操作可以說(shuō)是一項(xiàng)非常強(qiáng)大和有用的技能,尤其是在處理數(shù)據(jù)和位掩碼時(shí),它們是不可或缺的,本文將介紹JavaScript中的二進(jìn)制操作,包括什么是二進(jìn)制以及如何在JavaScript中進(jìn)行二進(jìn)制操作2023-06-06詳解嵌套命名空間在TypeScript中如何應(yīng)用
命名空間是TypeScript中非常有用的概念,可以幫助我們組織和管理代碼,避免命名沖突,下面小編就來(lái)和大家聊聊嵌套命名空間在TypeScript中是如何應(yīng)用的吧2023-06-06Grunt入門(mén)教程(自動(dòng)任務(wù)運(yùn)行器)
Grunt是一個(gè)自動(dòng)任務(wù)運(yùn)行器,會(huì)按照預(yù)先設(shè)定的順序自動(dòng)運(yùn)行一系列的任務(wù)。這可以簡(jiǎn)化工作流程,減輕重復(fù)性工作帶來(lái)的負(fù)擔(dān)2015-08-08Javascript 表格操作實(shí)現(xiàn)代碼
Javascript操作表格 包括獲取值,創(chuàng)建表格2009-06-06JavaScript Dom 綁定事件操作實(shí)例詳解
這篇文章主要介紹了JavaScript Dom 綁定事件操作,結(jié)合實(shí)例形式詳細(xì)分析了JavaScript實(shí)現(xiàn)dom綁定事件的相關(guān)實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下2019-10-10