若是你們看過北風網CJ講師的Javascript視頻教程,就能夠看到其封裝了一個很強的事件添加和刪除函數,以下所示javascript
1 function addEvent(obj, evtype, fn) { 2 //符合W3C的事件模型 3 if (obj.addEventListener) { 4 obj.addEventListener(evtype,fn,false); 5 return obj; 6 } 7 8 //IE或Opera瀏覽器 9 if (!obj.functions) obj.functions={}; 10 if (!obj.functions[evtype]) 11 obj.functions[evtype] = []; 12 13 var functions=obj.functions[evtype]; 14 for (var i=0;i<functions.length;i++) { 15 if (functions[i] === fn) return obj; 16 } 17 functions.push(fn); 18 19 20 if (typeof obj["on"+evtype]=="function") { 21 if (obj["on"+evtype]!=handler) 22 functions.push(obj["on"+evtype]); 23 } 24 obj["on"+evtype]=handler; 25 return obj; 26 } 27 28 29 function delEvent(obj,evtype,fn) { 30 if (obj.removeEventListener) { 31 obj.removeEventListener(evtype,fn,false); 32 return obj; 33 } 34 var fns=obj.functions || {}; 35 fns=fns[evtype] || []; 36 for (var i=0;i<fns.length;i++) { 37 if (fns[i]==fn) { 38 fns.splice(i,1); 39 return obj; 40 } 41 } 42 }
它由於各類緣由,沒有采用IE的DOM2級事件添加函數attachEvent,以期達到很是完美的兼容性,聽說能夠到 IE5.5 或如下。分析代碼頁能夠看到,它經過給DOM元素添加一個以 on + ‘type’ 爲名的屬性,其對應的值是一個處理函數的數組,本質來講就是僅僅利用 DOM0級提供的接口 elem.onclick = function () { ...} 來添加事件。html
一直以來沒有發現什麼問題,直到給別人使用時,發現IE6~8經過該封裝函數 addEvent 添加的 load 事件並無執行,調試代碼發現別人在 JS 中經過 window.onload 賦了一個處理函數,頓時明白這種 addEvent 封裝的一個大Bug,緣由很簡單,經過DOM0級提供的事件接口屢次添加時,後面的函數會覆蓋前面的,而這種 addEvent 本質上就是一個 DOM0級函數,因此確定會被後面的覆蓋。java
也就是說, addEvent 是假定網頁JS代碼中不使用 DOM0級添加事件。數組
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> 5 <script src="dom.event.js"></script> 6 <title>測試DOM0級事件和DOM2級事件的堆疊</title> 7 </head> 8 <body> 9 <textarea name="have" id="output" cols="30" rows="10"></textarea> 10 11 <button id="testBtn">測試</button> 12 13 <script type="text/javascript"> 14 var btn = document.getElementById('testBtn'); 15 var output = document.getElementById('output'); 16 17 18 // 標準的 DOM2 級事件添加方法 19 // if (btn.addEventListener) { 20 // btn.addEventListener('click', function () { 21 // output.value += 'DOM 2 Level Click\r\n'; 22 // }); 23 // } else { 24 // btn.attachEvent('onclick', function () { 25 // output.value += 'DOM 2 Level Click\r\n'; 26 // }) 27 // } 28 29 // 使用封裝的 addEvent 函數 30 // addEvent(btn, 'click', function () { 31 // output.value += 'DOM 2 Level Click\r\n'; 32 // }); 33 34 btn.onclick = function () { 35 output.value += 'DOM 0 Level Click 111111\r\n'; 36 } 37 38 btn.onclick = function () { 39 output.value += 'DOM 0 Level Click 222222\r\n'; 40 } 41 42 </script> 43 </body> 44 </html>
測試1:點擊測試按鈕,能夠看到textarea 中只是輸出 DOM 0 Level Click 22222 信息,也就是後面添加的事件覆蓋了以前添加的,跟變量賦值是一個道理!!瀏覽器
測試2:將 DOM2 級事件添加的代碼反註釋掉,打開網頁點擊測試按鈕,能夠看到會輸出 DOM 2 Level Click 和 DOM 0 Level Click 22222,也就是說DOM0 級事件和 DOM2 級添加的事件都會處理,DOM0級並不會覆蓋 DOM2 添加的事件處理函數。dom
測試3: 將 DOM2 級事件保持註釋狀態,反註釋掉 addEvent 部分, 能夠看到只會輸出 DOM 0 Level Click 22222。函數
測試4: 在測試3 的基礎上, 註釋掉後面兩個 DOM0 級添加事件的代碼,以測試 addEvent 的輸出,能夠看到它輸出 DOM 2 Level Click, 從而證實測試3中其被覆蓋的結論。測試
1) DOM0 級事件和 DOM2 級事件能夠共存;ui
2) 儘可能不要寫 DOM0 級事件,特別是代碼提供給別人使用時,絕對不能寫!spa