1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset=gb2312 /> 5 <title>js</title> 6 <script> 7 //function語句在解析時會被提高,無論function語句放置在哪裏, 8 //它都會被移動到所在做用域的頂層。 9 addEvent(window,'load',initAnchors); 10 11 12 function initAnchors(){ 13 for(var i=1; i<=3; i++){ 14 var anchor = $('anchor'+i); 15 registerListener(anchor,i); //函數中函數,也就是閉包,registerListener能夠保存外部變量的值。 16 } 17 }; 18 /* 19 把事件處理函數註冊到一個獨立的函數中。 20 21 如今click事件處理函數的外部做用域變成了registerListener()函數。 22 23 每次調用registerListener()函數時都會生成該函數的一個副本, 24 以維護正確的變量做用域。 25 */ 26 function registerListener(anchor,i){ 27 addEvent(anchor,'click',function(){ 28 alert('my id is anchor'+i); 29 }); 30 } 31 /* 32 由於i的值其實是單擊事件發生時才從做用域鏈中取得。 33 當單擊事件必發生時,initAnchors()已經執行完畢(驗證:在循環加入alert(i)後,打開網頁會彈出三次框)。 34 此時i=4。因此alert會顯示相同信息。 35 36 具體來講,當click事件處理函數被調用時,它會先在事件處理函數的內部做用域中查找i的值, 37 但click事件的匿名處理函數中沒有定義i的值,因此它再到其外部做用域(initAnchors()函數)中查找。 38 而外部做用域中i=4。 39 40 function initAnchors(){ 41 for(var i=1; i<=3; i++){ 42 //alert(i); 43 var anchor = $('anchor'+i); 44 addEvent(anchor,'click',function(){ 45 alert('my id is anchor'+i); 46 }); 47 } 48 }; 49 50 */ 51 function addEvent( node, type, listener ) { 52 if (node.addEventListener) { 53 // W3C method 54 node.addEventListener( type, listener, false ); 55 return true; 56 } else if(node.attachEvent) { 57 // MSIE method 58 //使用attachEvent()註冊的回調函數沒有Event參數,須要讀取Window對象的event屬性 59 //使用attachEvent()做爲全局函數調用。而不是事件發生其上的文檔元素的方法來調用 60 //也就是說attachEvent()註冊的回調函數執行時,this指向window對象,而不是事件目標元素。 61 //下面修正這些問題 62 node['e'+type+listener] = listener; 63 node[type+listener] = function(){ 64 node['e'+type+listener]( window.event ); 65 } 66 67 //IE事件模型不支持事件捕獲,因此須要兩個參數 68 node.attachEvent( 'on'+type, node[type+listener] ); 69 70 71 return true; 72 } 73 74 // Didn't have either so return false 75 return false; 76 }; 77 78 function $() { 79 var elements = new Array(); 80 81 // Find all the elements supplied as arguments 82 for (var i = 0; i < arguments.length; i++) { 83 var element = arguments[i]; 84 85 // If the argument is a string assume it's an id 86 if (typeof element == 'string') { 87 element = document.getElementById(element); 88 } 89 90 // If only one argument was supplied, return the element immediately 91 if (arguments.length == 1) { 92 return element; 93 } 94 95 // Otherwise add it to the array 96 elements.push(element); 97 } 98 99 // Return the array of multiple requested elements 100 return elements; 101 }; 102 </script> 103 </head> 104 105 <body> 106 <ul> 107 <li><a href="#" id="anchor1">Anchor 1</a></li> 108 <li><a href="#" id="anchor2">Anchor 2</a></li> 109 <li><a href="#" id="anchor3">Anchor 3</a></li> 110 </ul> 111 112 </body> 113 </html>