<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;300px">0</div>
<div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">1</div>
<div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">2</div>
<div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">3</div>
<div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">4</div>
<div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">5</div>
<div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;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;300px">0</div>
<div id="div1" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">1</div>
<div id="div2" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">2</div>
<div id="div3" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">3</div>
<div id="div4" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">4</div>
<div id="div5" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;300px">5</div>
<div id="div6" style=" border:1px solid #eee; background:#000;color:#fff;height:50px;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;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;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;300px">
</div>
<input type="button" value="click" οnclick="addDiv();">
</body>
</html>
我个人的理解是 在进入内层循环之前 把id赋值给f,f在作为内层循环的参数,其思想应该是一样的.