1.attachEvent與addEventListener的區別
- 支持的瀏覽器不同。
attachEvent
在IE9以下的版本中受到支持。其它的都支持addEventListener
。 - 參數不同。
addEventListener
第三個參數可以指定是否捕獲,而attachEvent
不支持捕獲。 - 事件名不同。
attachEvent
第一個參數事件名前要加on
,比如el.attachEvent('onclick', handleClick)。
this
不同。本文的將重點解釋
2.attachEvent方式的事件綁定
attachEvent
的this
總是Window
。例如:
el.attachEvent('onclick', function(){ alert(this); });
執行后會彈出對話框:[object Window]
。
3.addEventListener方式的事件綁定
addEventListener
的this
總是當前正在處理事件的那個DOM對象。 DOM Level 2 Event Model中提到,事件處理包括捕獲階段、目標階段和冒泡階段 。如下圖:
事件當前正在流過哪個元素,this
便指向哪個元素。比如對於兩級的DOM:
<div id="l1"> <div id="l2"></div> </div> <script type="text/javascript"> var l1 = document.getElementById('l1'), l2 = document.getElementById('l2'); l1.addEventListener('click', function () { console.log('l1 capture', this); }, true); l1.addEventListener('click', function () { console.log('l1 bubbling', this); }); l2.addEventListener('click', function () { console.log('l2 target', this); }); </script>
點擊div#l2
后控制台輸出為:
l1 capture <div id="l1">…</div> l2 target <div id="l2"></div> l1 bubbling <div id="l1">…</div>
4.糾正attachevent
Event.addEvent = function(target,eventType,handle){ target.attachEvent('on'+eventType,function(){ handle.call(currentTarget,arguments);//改變this指向 }); }
這里使用了currentTarget,我們再來順着分析一下target與currentTarget。
addEventListener
的事件處理函數中this
不一定指向事實上被點擊的元素, 但事件處理函數的參數Event對象提供了target
和currentTarget
屬性來區分這當前對象與目標對象。 我們可以把它們都全部輸出:
l1.addEventListener('click', function (e) { console.log('l1 capture', this, e.currentTarget, e.target); }, true); l2.addEventListener('click', function (e) { console.log('l2 target', this, e.currentTarget, e.target); }); l2.addEventListener('click', function (e) { console.log('l2 target, invalid capture', this, e.currentTarget, e.target); }, true);
結果是:
l1 capture <div id="l1">…</div> <div id="l1">…</div> <div id="l2"></div> l2 target <div id="l2"></div> <div id="l2"></div> <div id="l2"></div> l1 bubbling <div id="l1">…</div> <div id="l1">…</div> <div id="l2"></div>
可見currentTarget
總是和this
相同,而target
指向事實上被點擊的目標DOM對象。
5.補充:onclick在HTML和腳本中this指向的區別
腳本設置onclick方式的事件綁定
在javascript中設置DOM對象的onclick屬性,this
總是指向被設置的DOM元素。例如:
document .getElementById('l1') .onclick = function(){ console.log(this); };
點擊div#l1
后控制台輸出為:
<div id="l1">...</div>
HTML中設置onclick方式的事件綁定
在HTML中設置onclick
屬性相當於讓Window來調用該處理函數,於是this
總是Window
。例如:
<div onclick="clickHandler()"></div> <script> function clickHandler(){ console.log(this); } </script>
點擊這個div
后的控制台輸出為:
Window {top: Window, location: Location, document: document, window: Window, external: Object…}