JavaScript中的this關鍵字
在JavaScript中,this通常綁定到函數被調用的對象上,這種默認綁定在多數情況下是正常的,但是在某些情況下,this的這種綁定會丟失,比如,將函數作為參數傳遞給另外一個函數,這種默認的綁定就丟失了,例如:
var myObj = {
name: 'A nice demo!',
fx: function() {
alert(this.name);
}
};
function runFx(fx) {
fx();
}
window.name = 'I am a nice window';
myObj.fx(); // 在這里,將會提示 A nice demo!
runFx(myObj.fx); // 在這里,得到的提示將會是 I am a nice window
為什么會出現這種情況呢?因為在第二次調用中,myObj.fx作為參數傳遞給了runFx,在函數runFx中執行時fx丟失了對myObj的默認綁定,而綁定到了runFx的默認綁定window上,所以第二次調用時得到的提示為I am a nice window,而這個往往不是我們需要的結果。
在Ajax橫行的今天,要編寫復雜的客戶端組件,不可避免的要將函數名作為參數傳遞,Prototype注意到了這個問題,MS ASP.Net Ajax也注意到了這個問題,不知道你注意了沒有?
Prototype提供的解決方案是bind方法,在Prototype的官方文檔給出的描述是:Provides aguaranteed-binding equivalent of the original function, possibly with pre-filled arguments. 上面的例子如果使用Prototype的話,可以修改如下:
var myObj = {
name: 'A nice demo!',
fx: function() {
alert(this.name);
}
};
function runFx(fx) {
fx();
}
window.name = 'I am a nice window';
myObj.fx(); // 在這里,將會提示 A nice demo!
var fx2 = myObj.fx.bind(myObj) // 先做一個綁定,
runFx(fx2); // 在這里,得到的提示將會是 A nide demo !這個往往是我們需要的結果
MS Ajax提供的解決方案是Function.createDelegate函數,createDelegate方法是個靜態方法,可以直接調用。如果使用MS Ajax庫的話,可以將上面的例子修改為:
var myObj = {
name: 'A nice demo!',
fx: function() {
alert(this.name);
}
};
function runFx(fx) {
fx();
}
window.name = 'I am a nice window';
myObj.fx(); // 在這里,將會提示 A nice demo!
var fx2 = Function.createDelegate(myObj, myObj.fx) // 按照微軟的說法,先做一個委托,
runFx(fx2); // 在這里,得到的提示將會是 A nide demo !這個往往是我們需要的結果
這看起來只是一個小問題,但是如果不注意的話卻會造成很大的問題。引用Prototype中的原話:As discussed on the general Function page,binding can be a pretty tricky thing sometimes.
張志敏所有文章遵循創作共用版權協議,要求署名、非商業 、保持一致。在滿足創作共用版權協議的基礎上可以轉載,但請以超鏈接形式注明出處。
本博客已經遷移到 GitHub , 圍觀地址: https://beginor.github.io/
浙公網安備 33010602011771號