在用js編寫頁面事件處理代碼時,會經常涉及到this和event對象,但有時在采用不同的事件處理,尤其是在與自定義的對象關聯時,這些對象的指向變的有些復雜。
本文來詳細介紹下各種場景下 這些對象 真正指向。
一、事件直接寫在html標簽中
1、案例1:
<button onclick="clickBtn()">測試</button>
處理代碼如
function clickBtn(){
alert(this.location.href);
}
這時的 this 是指向全局 Window對象。
2、案例2:
<button onclick="clickBtn(this)">測試</button>
處理代碼如
function clickBtn(obj){
alert(obj.innerHTML);
}
這時的 上述方法中的 obj指向的是按鈕本身。也就是在 onclick="clickBtn(this)"傳入的this對象指向事件觸發的按鈕。
3、冒泡
<div onclick="clickBtn(this)"><button >測試</button></div>
因為html事件的冒泡特性,雖然上面的onclick事件寫在div上,這時無論是點擊按鈕還是div區域,都會觸發div上綁定的事件。
但無論點擊的是哪個,會發現 事件響應傳入的 this指向的是 div,不是button.
在這種方式下,我們除了可以將this對象傳給事件處理函數外,還可以將event對象傳給事件處理函數。event對象包含了觸發事件的各種信息。
<button onclick="clickBtn(event)">測試</button>
4、事件響應函數為對象的方法
我們看下,如果事件響應的函數為對象的方法,會出現什么變化。
<button onclick="handleDemo.clickBtn(this)">測試</button>
代碼如下
<script>
function HandleDemo(){
this.msg="good";
}
HandleDemo.prototype.clickBtn=function(obj){
alert(obj.innerHTML);
alert(this.msg);
}
var handleDemo = new HandleDemo();
</script>
這時會發現 clickBtn 方法中的 this 指向的是 handleDemo 對象。 參數obj因為是傳入的,指向的是button對象,這個沒變。
說明:直接在html標簽中綁定事件,是一件非常不好的編碼習慣,強烈不建議推薦。下面我們介紹用jquery進行事件處理。
二、利用jquery綁定事件
1、方式一:
<button id="btn">測試</button>
腳本代碼
<script> $("#btn").click(clickBtn); function clickBtn(event){ alert(this.innerHTML); alert(event.currentTarget.innerHTML); } </script>
上面代碼 通過調用jquery對象的 click方法,參數就是事件響應處理函數。
這個函數可以帶一個參數,jquery會把事件對象event傳入。參數名可以是任意的,不一定叫event。
如果不定義參數,在函數中也可直接使用event。但一般如果需要用到event對象,最好顯式定義下。
這時我們會發現,在函數體中直接使用的this指向的是 button對象。 我們可以不顯示的定義對象,采用匿名函數的方式,如:
<script> $("#btn").click(function(ev){ alert(this.innerHTML); alert(ev.currentTarget.innerHTML); }); </script>
這個代碼與上面代碼的效果完全一樣。
我們再來看下,如果傳給click方法的是對象的方法呢?
<script>
function HandleDemo(){
this.msg="good";
}
HandleDemo.prototype.clickBtn=function(ev){
alert(this.innerHTML);
alert(ev.currentTarget.innerHTML);
}
var handleDemo = new HandleDemo();
$("#btn").click(handleDemo.clickBtn);
</script>
這時,我們發現clickBtn中的 this指向的依然是 button對象,並不是我們想象中的 handleDemo對象。
這樣就帶來一個很大的問題,因為clickBtn方法是handleDemo對象的成員,如果我們想要在clickBtn方法中訪問handleDemo對象的其它成員,卻沒辦法了。
除非直接使用全局變量,而這是很不推薦的。
下面我們介紹jquery的另外一種事件綁定方法。
2、方式二:bind方法
html代碼依然不變
<button id="btn">測試</button>
腳本代碼
<script>
function clickBtn(ev){
alert(this.innerHTML);
alert(ev.currentTarget.innerHTML);
}
$("#btn").bind("click",clickBtn);
</script>
這時,事件處理方法依然有一個參數指向event對象。
我們發現 clickBtn中的 this 指向的是 button對象。
bind函數,有三個參數,第一個是代表事件類型;第二個是傳遞給事件處理的額外信息對象(會賦值給event的data屬性);第三個是事件處理函數。
上面例子我們只使用了第1個和第3個。下面我們看下例子:
<script>
function clickBtn(ev){
alert(this.innerHTML);
alert(ev.currentTarget.innerHTML);
alert(ev.data.msg);
}
$("#btn").bind("click",{msg:"hello"},clickBtn);
</script>
采用這種方式,我們傳遞了額外的對象給事件處理函數。這在某些場景下還是能用到的。
下面我們看下這種方式下傳入的事件處理函數是對象的方法:
<script>
function HandleDemo(){
this.msg="good";
}
HandleDemo.prototype.clickBtn=function(ev){
alert(this.innerHTML);
alert(ev.currentTarget.innerHTML);
alert(ev.data.msg);
}
var handleDemo = new HandleDemo();
$("#btn").bind("click",handleDemo,handleDemo.clickBtn);
</script>
我們可以將對象本身作為bind方法的第二個參數傳入。以解決在方法中無法訪問對象其它成員的問題。
注意:采用jquery的事件綁定,無論是用bind方法,還是上一種方法。 如果調用多次,會綁定多次,而不會后面的覆蓋前面的,事件觸發時,事件函數會被多次執行。
