使用闭包时,理解 内部函数是直接访问外部函数的实际变量,而非复制一份新变量是非常重要的 (!).下面是一个错误示范:
1 <BODY> 2 <INPUT TYPE="button" name='tt' VALUE="按钮1"> 3 <INPUT TYPE="button" NAME="tt" VALUE="按钮2"> 4 <INPUT TYPE="button" NAME="tt" VALUE="按钮3" ONCLICK=""> 5 6 <SCRIPT LANGUAGE="JavaScript"> 7 <!-- 8 var add_the_handlers = function(nodes){ 9 var i; 10 for(i = 0 ; i < nodes.length ; i ++){ 11 nodes[i].onclick = function(e){ 12 //(!) 直接访问了外部变量i, 并不是复制一份i的实例。 13 //所以随着i一直自增,最后弹出来的均是nodes.length 14 alert(i); //执行按钮点事件的时候 i的值是定义的那个i的值, 15 } 16 } 17 18 i=9//点击按钮的时候, 弹出 9 19 } 20 add_the_handlers( document.getElementsByName("tt") ) 21 //--> 22 </SCRIPT>
矫正方法:
1 <BODY> 2 <INPUT TYPE="button" name='tt' VALUE="按钮1"> 3 <INPUT TYPE="button" NAME="tt" VALUE="按钮2"> 4 <INPUT TYPE="button" NAME="tt" VALUE="按钮3" > 5 6 <SCRIPT LANGUAGE="JavaScript"> 7 <!-- 8 var add_the_handlers = function(nodes){ 9 //alert("开始执行") 10 var i; 11 for(i = 1 ; i < nodes.length ; i ++){ 12 //alert("执行到for循环中:"+i) 13 nodes[i].onclick = function(i){ 14 //alert("返回方法之前执行: "+i) 15 return function(e){ // 返回另一个匿名函数,但是该函数可以访问外面匿名函数构造时传入的 i 实例. 16 alert(i); 17 }; 18 }(i); // 立即调用匿名函数 function(i); 19 } 20 //alert("执行结束") 21 } 22 add_the_handlers( document.getElementsByName("tt") ) 23 //--> 24 </SCRIPT>
闭包示例:函数依然可以访问 value的值(闭包).
1 <BODY> 2 <SCRIPT LANGUAGE="JavaScript"> 3 <!-- 4 var myObject_protected = function(){ 5 6 // 这里通过一个函数的形式初始化了对象。由于函数作用域的关系,内部 7 // 函数依然可以访问 value的值(闭包). 8 var value = 0; 9 return { 10 increment : function(inc){ 11 value += (typeof inc === 'number' ? inc : 1); 12 }, 13 getValue : function(){ 14 return value; 15 } 16 }; 17 }; 18 19 var myObject_p = new myObject_protected(); 20 myObject_p.increment(10); //调用一次10 21 myObject_p.increment(10); //调用二次20 22 document.writeln(myObject_p.getValue()); 23 //--> 24 </SCRIPT> 25 </BODY>