jQuery AJAX回呼函數this指向問題

來源:互聯網
上載者:User

如在全域範圍調用一個含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)});

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.