Contents

[JavaScript] IE/W3C Event用法大不同

在撰寫跨瀏覽器的 JavaScript 時,事件綁定是最常遇到相容性問題的地方之一。IE 早期版本使用自己的 attachEvent,而其他符合 W3C 標準的瀏覽器則使用 addEventListener,兩者在語法與行為上有明顯差異。

事件名稱差異

W3C 標準使用不帶 on 前綴的事件名稱,而 IE 的 attachEvent 需要加上 on

1
2
3
4
5
// W3C 標準
element.addEventListener('click', handler, false);

// IE 舊版
element.attachEvent('onclick', handler);

this 的指向差異

這是最常造成 bug 的地方。使用 addEventListener 時,回呼函式內的 this 指向綁定事件的元素本身;但使用 attachEvent 時,this 指向的是全域物件 window

1
2
3
4
5
6
7
element.addEventListener('click', function() {
    console.log(this); // 指向 element
});

element.attachEvent('onclick', function() {
    console.log(this); // 指向 window,不是 element!
});

事件傳遞方向

addEventListener 第三個參數可以控制事件傳遞方向(捕獲或冒泡),attachEvent 則只支援冒泡階段。

跨瀏覽器相容寫法

可以撰寫一個通用的事件綁定函式,自動偵測瀏覽器支援哪種方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function addEvent(element, eventName, handler) {
    if (element.addEventListener) {
        // W3C 標準瀏覽器
        element.addEventListener(eventName, handler, false);
    } else if (element.attachEvent) {
        // IE 舊版,修正 this 指向問題
        element.attachEvent('on' + eventName, function() {
            handler.call(element);
        });
    }
}

// 使用範例
addEvent(document.getElementById('btn'), 'click', function() {
    console.log(this.id); // 正確指向元素
});

移除事件

同樣地,移除事件也有差異:

1
2
3
4
5
// W3C
element.removeEventListener('click', handler, false);

// IE 舊版
element.detachEvent('onclick', handler);

總結

特性 W3C (addEventListener) IE 舊版 (attachEvent)
事件名稱 click onclick
this 指向 綁定的元素 window
捕獲/冒泡 支援 僅冒泡
移除方式 removeEventListener detachEvent

現代開發中,IE 的市占率已大幅降低,主流框架(如 jQuery、React)也都自動處理了這些差異。若需支援非常舊的 IE 版本,使用上述的跨瀏覽器封裝函式是最簡潔的做法。