JS的一个比较奇怪的问题,据说是闭包导致的

scy251147 2011-01-11 06:13:25
代码如下:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Untitled</title>
<script>
function func() {
var i;
for (i = 1; i <= 4; i++) {
var el = document.getElementById('closureExample' + i);
el.onclick = function() { alert(i) };

}
}

window.onload = function() {
func();
}
</script>
</head>

<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子3</a>
</body>
</html>


我的本意:
是想单击例子1,例子2,例子3,例子4的时候,分别弹出1,2,3,4的,但是结果却发现弹出的都是5
我估计如下:
绑定的时候,是动态绑定的,只不过将事件绑定到了元素身上而已,但是参数却是在变的
当i==4的时候,由于运行了i++所以最终成了5 显示出来的结果当然是5了
我的猜想:
是不是在绑定的时候先运行一下click事件就可以解决这个问题呢?
现在寻求如何解决这一问题
...全文
267 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaeelee 2011-01-13
  • 打赏
  • 举报
回复
el.onclick = function() { alert(i) };
这样只创建了一层闭包,alert显示的变量i就是外层函数里的局部变量,循环结束之后,他的值被改变成5了,所以,触发点击事件的时候引用的还是这个变量,其值是5


el.onclick = (function(n) {
return function() {alert(n);}
})(i)
这种 做法创建了两层闭包,alert显示的变量在匿名函数里的参数,他是以参数的形式传递进来的,后面也没有操作改变这个值,所以一次点击会有不同的值,实际上与上面不同的是,alert显示的i引用了不同的变量,而上面的例子却引用了相同的变量
hch126163 2011-01-12
  • 打赏
  • 举报
回复
js 闭包

楼上几位正解
  • 打赏
  • 举报
回复
el.onclick = function() { alert(i) };
这是活的


el.onclick = (function(n) {
return function() {alert(n);}
})(i)
这是死的

这样理解就直观了
fxs_2008 2011-01-12
  • 打赏
  • 举报
回复
理解闭包的好例子啊
yuanrong303 2011-01-12
  • 打赏
  • 举报
回复
所谓闭包是跟函数定义的上下文(context)和作用域(scope)共同决定的。

function func() {
var i;
for (i = 1; i <= 4; i++) {
var el = document.getElementById('closureExample' + i);
el.onclick = function() { alert(i) }; //这个函数的上下文是func函数,这样onclick能访问func函数定义的i变量,他没有绑定那个值,只是能访问上下文的变量,这样最终执行onclick时i已经在这个上下文中有固定值5,所以全部onclick都显示5
}


马老虎 2011-01-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 cj205 的回复:]

引用 12 楼 mmm306306 的回复:

引用 11 楼 mmm306306 的回复:



即时执行
这是我自己给这种方法的称呼。忘了官方的称呼叫啥了
自执行函数
[/Quote]
哦 谢谢啦。
madpc 2011-01-12
  • 打赏
  • 举报
回复
最简单的方法就是用 jquery 之类框架的 each , 自已写一个 each 也很容易

我自已实现了这种方式
new Array().fillRange(1,4).each(function(i){
document.getElementById("closureExample"+i).onclick = function(n) {
alert(i)
}

})
prototyper 2011-01-11
  • 打赏
  • 举报
回复
function func() {
for (var i = 1; i <= 4; i++) {
with ({i:i}) {
var el = document.getElementById('closureExample' + i);
el.onclick = function() { alert(i) };
}
}
}
Mr-Jee 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 mmm306306 的回复:]

引用 11 楼 mmm306306 的回复:



即时执行
这是我自己给这种方法的称呼。忘了官方的称呼叫啥了
[/Quote]自执行函数
马老虎 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 mmm306306 的回复:]


[/Quote]
即时执行
这是我自己给这种方法的称呼。忘了官方的称呼叫啥了
马老虎 2011-01-11
  • 打赏
  • 举报
回复
也开始使用 即时执行 的办法。



function func() {
for (i = 1; i <= 4; i++) {
var el = document.getElementById('closureExample' + i);

(function(){
var ii = i;
el.onclick = function(){ alert(ii);};

})();


}
}
scy251147 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 cj205 的回复:]
就是闭包
函数绑定的是变量i
但是循环结束之后i的值已经变了
这个时候你触发事件调用的i就是最大的值了


关于闭包 http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html 是最好的文档。
[/Quote]
恩 谢谢啦,我去看看去
打字员 2011-01-11
  • 打赏
  • 举报
回复

function func() {
for (var i = 1; i <= 4; i++) {
var el = document.getElementById('closureExample' + i);
el.setAttribute('index', i);
el.onclick = function() {
alert(this.getAttribute('index'));
};
}
}
scy251147 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 cj205 的回复:]
HTML code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Untitled</title>
<script>
function func() {
var i;
for (i = 1; i <……
[/Quote]
非常感谢你 是对的 我还真不了解js的闭包,能给稍微讲解下吗?
Mr-Jee 2011-01-11
  • 打赏
  • 举报
回复
就是闭包
函数绑定的是变量i
但是循环结束之后i的值已经变了
这个时候你触发事件调用的i就是最大的值了


关于闭包 http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html 是最好的文档。
Crazywa 2011-01-11
  • 打赏
  • 举报
回复
cj锅正解。
i的作用域是整个func函数。
在onclick的时候func函数内部的i已经是5了。
用cj锅那种形式,在i还是1/2/3/4/5的时候,分别传入匿名函数中,在匿名函数的环境中,存储了i在执行函数时的值,也就是分别是1 2 3 4 5
Mr-Jee 2011-01-11
  • 打赏
  • 举报
回复
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Untitled</title>
<script>
function func() {
var i;
for (i = 1; i <= 4; i++) {
document.getElementById("closureExample"+i).onclick = (function(n) {
return function() {alert(n);}
})(i)
}
}

window.onload = function() {
func();
}
</script>
</head>

<body>
<a href="#" id="closureExample1">例子1</a>
<a href="#" id="closureExample2">例子2</a>
<a href="#" id="closureExample3">例子3</a>
<a href="#" id="closureExample4">例子3</a>
</body>
</html>
scy251147 2011-01-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 cj205 的回复:]
el.onclick = function() { alert(i) };
==>
el.onclick = (function(n) {
return function() {alert(n);}
})(i)
[/Quote]
能说明下为什么吗?我没看懂,或者是有什么资料我能参考下吗?
Mr-Jee 2011-01-11
  • 打赏
  • 举报
回复
el.onclick = function() { alert(i) };
==>
el.onclick = (function(n) {
return function() {alert(n);}
})(i)

87,921

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧