js中擷取事件對象的方法小結

來源:互聯網
上載者:User

複製代碼 代碼如下:
var evt = window.event || arguments[0];

下面分三種添加事件的方式討論,你也許會看到以前沒有看到過的擷取方式。
1,第一種添加事件的方式,直接在html的屬性中寫JS代碼
複製代碼 代碼如下:
<div onclick="alert(4);">Div1 Element</div>

大概這是上世紀90年代的寫法,那時候直接把js代碼寫在網頁中很普遍,也許那時候的js並不太重要,只是用來做做驗證或一些花哨的效果而已。如何在這種添加事件方式下擷取到事件對象?IE中很簡單,因為event是作為全域對象的,所以直接使用event即可,如下
複製代碼 代碼如下:
<div onclick="alert(window.event.type);">Div1 Element</div>

點擊該Div後,IE中會彈出'click'字元的資訊框。說明事件對象擷取到了,如果在 Opera/Safari/Chrome 中也測試了,會發現效果和IE一樣,說明 Opera/Safari/Chrome 中也支援IE方式( window.event )擷取事件對象。
Firefox中會報錯,提示:window.event is undefined,說明Firefox不支援IE方式擷取事件對象而是以控制代碼的第一個參數傳入的,文章開頭意見提到了。
上面的用 window.event 來擷取事件對象,其實window可以省略的,就像使用alert而不是window.alert一樣。如
複製代碼 代碼如下:
<div onclick="alert(event.type);">Div1 Element</div>

在 IE/Opera/Safari/Chrome 中測試,和剛剛不會有什麼區別。在Firefox中再測,會有個驚喜,你會發現居然彈出的是"click"資訊框,而不是"undefined"。
兩次測試區別僅僅一個用window.event.type,一個用event.type。這個問題下面詳細討論。
下面用控制代碼第一個參數來擷取事件對象,可以把onclick屬性的值想象成一個匿名函數,onclick屬性值的字串實際上都是這個匿名函數內的js代碼。
既然這樣,我們就可以通過Function的一個屬性argumengs擷取到該匿名函數的第一個參數,而該參數就是事件對象。如
複製代碼 代碼如下:
<div onclick="alert(arguments[0].type);">Div1 Element</div>

IE中會報錯,提示:arguments.0.type為空白或不是對象
Firefox/Opera/Safari/Chrome 中會彈出"click"內容的資訊框,說明他們都支援事件對象作為控制代碼第一個參數傳入。從側面也說明了 Opera/Safari/Chrome 不僅支援W3C標準方式擷取事件對象,同時也相容了IE方式擷取事件對象。
既然知道onclick對應的是一個匿名函數,我們不妨把該匿名函數列印出來看看,只需以下代碼
複製代碼 代碼如下:
<div onclick="alert(arguments.callee);">Div1 Element</div>

在各瀏覽器中點擊該Div,結果如下:

IE6/7/8 :

function onclick(){ alert(arguments.callee);}

IE9 :

 function onclick(event){ alert(arguments.callee);}

Firefox / Safari :
function onclick(event) { alert(arguments.callee);}

Chrome :
function onclick(evt) { alert(arguments.callee);}

Opera :

 function anonymous(event) {alert(arguments.callee);}

觀察這些函數發現:
IE6/7/8沒有定義參數
IE9/Firefox/Safari/Opera 定義了參數event
Chrome定義了參數evt。
現在回到上面遺留的問題,如下
複製代碼 代碼如下:
<div onclick="alert(window.event.type);">Div1 Element</div>
<div onclick="alert(event.type);">Div1 Element</div>

這兩個div的區別僅window.event.type和event.type。分別點擊後,後者在Firefox中不彈出"undefined",而是"click",是因為Firefox中匿名函數定義了參數event,該參數剛好與IE的全域對象event同名,從而誤以為Firefox也支援IE方式擷取事件對象。

同樣的道理,Chrome中定義的參數是evt,那麼在Chrome中還可以通過以下方式擷取事件對象,如下
複製代碼 代碼如下:
<div onclick="alert(evt);">Div1 Element</div>

2,第二種添加事件的方式,定義一個函數,賦值給html元素的onXXX屬性
複製代碼 代碼如下:
<script type="text/javascript">
function clk(){}
</script>
<div onclick="clk()">Div2 Element</div>

先定義函數clk,然後賦值給onclick屬性,這種方式也應該屬於上世紀90年代的流行寫法。比第一種方式好的是它把商務邏輯代碼都封裝在一個函數裡了,使HTML代碼與JS代碼稍微有點兒分離,不至於第一種那麼緊密耦合。
如何在這種方式(clk函數內)中擷取事件對象?IE中使用全域對象event仍然沒問題,如:
複製代碼 代碼如下:
<script type="text/javascript">
function clk(){alert(window.event);}
</script>
<div onclick="clk()">Div2 Element</div>

點擊Div後,除Firefox外,IE/Opera/Safari/Chrome都能正常擷取事件對象。上面已經提到了 Opera/Safari/Chrome 相容IE方式(window.event)擷取事件對象,而唯獨Firefox不支援。從而Firefox中只能通過參數傳入了。試著這麼寫
複製代碼 代碼如下:
<script type="text/javascript">
function clk(){alert(event);}
</script>
<div onclick="clk()">Div2 Element</div>

因為在Firefox中匿名函數是具有event參數的,而clk()是在匿名函數之內的,列印出匿名函數便知
複製代碼 代碼如下:
<script type="text/javascript">
function clk(){alert(arguments.callee.caller);}
</script>
<div onclick="clk()">Div2 Element</div>

點擊該Div,Firefox彈出資訊框內容如下
複製代碼 代碼如下:
function onclick(event) {
clk();
}

回到clk中的alert(event),既然匿名函數的event傳入了,那麼在該閉包中clk是可以擷取到event的,事實上點擊後Firefox會報錯:event is not defined。猜測該匿名函數的閉包和function clk(){alert(event);}不是同一個閉包環境。這種方式不行,則只能通過顯示的參數傳入了,如
複製代碼 代碼如下:
<script type="text/javascript">
function clk(e){alert(e);}
</script>
<div onclick="clk(arguments[0])">Div2 Element</div>

點擊Div,在Firefox中正確彈出了事件對象,支援參數傳入的瀏覽器都可以,如Opera/Safari/Chrome。
把以上代碼中的arguments[0]改成event,那麼所有瀏覽器都支援。
把以上代碼中的arguments[0]改成window.event,那麼將只有Firefox不支援。
把以上代碼中的arguments[0]改成evt,那麼將只有Chrome支援。
思考下為什嗎?
3,第三種添加事件方式,使用element.onXXX方式
複製代碼 代碼如下:
<div id="d3">Div3 Element</div>
<script type="text/javascript">
var d3 = document.getElementById('d3');
d3.onclick = function(){ }
</script>

這種方式也比較早期,但好處是可以將JS與HTML完全分離,但前提是需要給HTML元素提供一個額外的id屬性(或其它能擷取該元素對象的方式)。
這種方式添加事件IE6/7/8隻支援window.event不支援參數傳入,Firefox只支援參數傳入不支援其它方式。IE9/Opera/Safari/Chrome 兩種方式都支援。
4,第四種添加事件方式,使用addEventListener或IE專有的attachEvent
複製代碼 代碼如下:
<div id="d4">Div4 Element</div>
<script type="text/javascript">
var d4 = document.getElementById('d4');
function clk(){alert(4)}
if(d4.addEventListener){
d4.addEventListener('click',clk,false);
}
if(d4.attachEvent){
d4.attachEvent('onclick',clk);
}
</script>

這是目前推薦的方式,較前兩種方式功能更為強大,可以為元素添加多個控制代碼(或稱響應函數),支援事件冒泡或捕獲,前三種方式預設都是冒泡。當然IE6/7/8仍然沒有遵循標準而使用了自己專有的attachEvent,且不支援事件捕獲。IE9 中已經支援addEventListener了。
先用window.event測試,如
複製代碼 代碼如下:
<script type="text/javascript">
var d4 = document.getElementById('d4');
function clk(){alert(window.event)}
if(d4.addEventListener){
d4.addEventListener('click',clk,false);
}
if(d4.attachEvent){
d4.attachEvent('onclick',clk);
}
</script>

點擊Div[id=d4],IE/Opera/Safari/Chrome都正確的彈出了事件對象資訊框,Firefox彈出的是"undefined",預料之中,因為Firefox不支援window.event作為事件對象。
再換成控制代碼的第一個參數測試,如
複製代碼 代碼如下:
<script type="text/javascript">
var d4 = document.getElementById('d4');
function clk(e){alert(e)}
if(d4.addEventListener){
d4.addEventListener('click',clk,false);
}
if(d4.attachEvent){
d4.attachEvent('onclick',clk);
}
</script>

測試之前,猜測一下什麼結果,可能有人會覺得IE中應該彈出undefined,其它瀏覽器都是事件對象。事實上所有瀏覽器彈出的資訊框顯示都是事件對象。
總結下:
1,IE6/7/8支援通過window.event擷取對象,通過attachEvent方式添加事件時也支援事件對象作為控制代碼第一個參數傳入
2,Firefox只支援事件對象作為控制代碼第一個參數傳入
3,IE9/Opera/Safari/Chrome兩種方式都支援

相關:
各瀏覽器事件對象差異性列表

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.