作用域链 《javascript DOM高级程序设计》 P35页
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript" src="ADS-start.js"></script> <script type="text/javascript"> function initAnchors(){ for(var i=1;i<=3;i++){ var anchor = document.getElementById('anchor'+i); ADS.addEvent(anchor,'click',function(){ alert('my id is anchor '+i); }); } } ADS.addEvent(window,'load',initAnchors); </script> </head> <body> <ul> <li><a href="" id="anchor1">anchor1</a></li> <li><a href="" id="anchor2">anchor2</a></li> <li><a href="" id="anchor3">anchor3</a></li> </ul> </body> </html>
点击后都会弹出''my id is anchor 4'
我们想要的结果是我们点击第几个出现的就是相关的数字,'my id is anchor 1',为什么会这样呢?因为不的值实际上是在单击事件发生时才从作用域链中取得的,当单击事件发生时,initAnchors()已经执行完毕,因此i的值等于4,所以每个alert都会显示相同的信息。具体来说,当click事件侦听器被调用并在它的内部作用域中查找i的值时,结果没有找到,因为i的值在作用click事件侦听器的匿名函数中没有定义。
要得到正确的结果,需要把事件侦听器的注册转移到一个独立的函数中,并通过该函数的参数传递适当的值
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>无标题文档</title> <script type="text/javascript" src="ADS-start.js"></script> <script type="text/javascript"> function registerListener(anchor,i){ ADS.addEvent(anchor,'click',function(){ alert('my id is anchor '+i); }); } function initAnchors(){ for(var i=1;i<=3;i++){ var anchor = document.getElementById('anchor'+i); registerListener(anchor,i); } } ADS.addEvent(window,'load',initAnchors); </script> </head> <body> <ul> <li><a href="" id="anchor1">anchor1</a></li> <li><a href="" id="anchor2">anchor2</a></li> <li><a href="" id="anchor3">anchor3</a></li> </ul> </body> </html>
由于在作用域链中定义了额外的函数和变量,提示信息中保持了正确的值。因为click事件侦听器现在的外部使用域变成了
registerListener()函数,该函数在其每个实例(每次调用registerListener()函数都会生成该函数的一个副本,以维护正确的变量作用域)的内部作用域中都为i维护了一个唯一值。