javascript 常见的闭包问题的解决办法

<html> 
<head> 
<title></title> 
<script type="text/javascript"> 
<!-- 
function $(elem){ 
return document.getElementById(elem); 
} 
function tag(name,elem) 
{ 
return (elem||document).getElementsByTagName(name); 
} 

function init() 
{ 
var div=tag("div"); 
for(var i=0;i<div.length;i++) 
{ 
div[i].οnclick=function() 
{ 
alert(i); 
} 
} 
} 
// --> 
</script> 
</head> 
<body> 
<div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">0</div> 
<div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">1</div> 
<div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">2</div> 
<div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">3</div> 
<div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">4</div> 
<div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">5</div> 
<div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">6</div> 
<input type="button" value="click" οnclick="init();"> 
</body> 
</html>

上段代码本意是在每个div上都加一个事件,即每当点击div时,就显示此div的相应序号。但是运行程序时我们会发现,不论点击那个,只会显示7,这是什么愿因呢。--这就是闭包的问题 
原来 在js中,函数中在定义函数,就出现闭包了。此时外层函数中变量是可以在里层函数里利用的,即使外层函数结束。但是当外层中出现循环的时候,如果在里层函数中利用这个循环变量的话,会直接引用这个变量的最终值。 
就像上述代码演示的一样。 
如何解决呢。 
可以利用匿名函数来加以解决。匿名函数会制动执行,我们可以利用这一特性,来产生一个作用域,生命一个变量,来引用外层的循环变量。 
如代码所示: 

 

<html> 
<head> 
<title></title> 
<script type="text/javascript"><!-- 
function $(elem){ 
return document.getElementById(elem); 
} 
function tag(name,elem) 
{ 
return (elem||document).getElementsByTagName(name); 
} 

function init() 
{ 
var div=tag("div"); 
for(var i=0;i<div.length;i++){ 
(function(){ 
var temp=i; 
div[temp].οnclick=function() 
{ 
alert(temp); 
} 


})() 

} 
} 
// --></script> 
</head> 
<body> 
<div id="div" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">0</div> 
<div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">1</div> 
<div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">2</div> 
<div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">3</div> 
<div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">4</div> 
<div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">5</div> 
<div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;width:300px">6</div> 
<input type="button" value="click" οnclick="init();"> 
</body> 
</html>




由于在内层函数里只要出现循环变量的话 都是最终值,所以我们利用匿名函数 激发出一个作用域,在进入内层循环之前,有另一变量获得该循环变量的值,这一思想是处理闭包问题的精髓。 

如下例子:此时并没有明显的for循环,但是 根据上述思想,可以立即加以解决 问题 

 

<html> 
<head> 
<title> </title> 
<script type="text/javascript"><!-- 

function $(elem){ 
return document.getElementById(elem); 
} 
var id=0; 
function addDiv() 
{ 
var text="testtestetsetstsetstst"; 
var div=$("div"); 
var divChild=document.createElement("div"); 
div.appendChild(divChild); 
divChild.id="div"+id; 
divChild.innerHTML=" <input type='text' id='row"+id+"'>"+text; 
divChild.οnclick=function() 
{ 
alert("row"+id); 
$("row"+id).value=text; 
} 
id++; 
} 
// --></script> 
</head> 
<body> 
<div id="div" style="height:200px;width:300px"> 
</div> 
<input type="button" value="click" οnclick="addDiv();"> 
</body> 
</html>


解决后代码:

<html> 
<head> 
<title> </title> 
<script type="text/javascript"><!-- 

function $(elem){ 
return document.getElementById(elem); 
} 
var id=0; 
function addDiv() 
{ 
var text="testtestetsetstsetstst"; 
var div=$("div"); 
var divChild=document.createElement("div"); 
div.appendChild(divChild); 
divChild.id="div"+id; 
divChild.innerHTML=" <input type='text' style='color:#f00' id='row"+id+"'>"+text; 
(function(){ 
var d=id; 
divChild.οnclick=function() 
{ 

alert("row"+d); 
$("row"+d).value=text; 

} 

})() 
id++; 
} 
// --></script> 
</head> 
<body> 
<div id="div" style="height:200px;width:300px"> 
</div> 
<input type="button" value="click" οnclick="addDiv();"> 
</body> 
</html>


 


补充:看到有网友这样解决了问题: 

 

<html> 
<head> 
<title> </title> 
<script type="text/javascript"><!-- 

function $(elem){ 
return document.getElementById(elem); 
} 
var id=0; 
function addDiv() 
{ 
var text="testtestetsetstsetstst"; 
var div=$("div"); 
var divChild=document.createElement("div"); 
div.appendChild(divChild); 
divChild.id="div"+id; 
divChild.innerHTML=" <input type='text' style='color:#f00' id='row'"+id+">"+text; 

divChild.οnclick=function(f){ 
return function(){ 
alert(f); 
} 
}(id) 

id++; 
} 
// --></script> 
</head> 
<body> 
<div id="div" style="background:#000;color:#fff;height:200px;width:300px"> 
</div> 
<input type="button" value="click" οnclick="addDiv();"> 
</body> 
</html> 

 


我个人的理解是 在进入内层循环之前 把id赋值给f,f在作为内层循环的参数,其思想应该是一样的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值