最近看到这样一道题:为什么点击所有的段落p输出都是4,而不是alert出对应的0,1,2,3,应该如何解决?
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>我是p0</p>
<p>我是p1</p>
<p>我是p2</p>
<p>我是p3</p>
<script type="text/javascript">
function init(){
var pAry=document.getElementsByTagName("p");
for(var i=0;i<pAry.length;i++){
pAry.οnclick= function () {
alert(i);
}
}
}
init();
</script>
</body>
</html>
原因是由于JavaScript的闭包特性。通过element.οnclick=function(){alert(i);}方式给元素添加点击事件。响应函数function(){alert(i);}中的 i 并非每次循环时对应的 i (如0,1,2,3,4),而是循环后最后 i 的值5.或者说循环时响应函数内并未能保存对应的值 i ,而是最后一次i++的值5.
这里介绍两种解决方法:
方法一:将每次循环的i添加到pAry的属性i中
function init(){
var pAry=document.getElementsByTagName("p");
for(var i=0;i<pAry.length;i++){
pAry[i].i=i;
pAry[i].οnclick= function () {
alert(this.i);
}
}
}
init();
方法二:在函数中创建一个闭包,将每次循环的i传入闭包中输出
function init(){
var pAry=document.getElementsByTagName("p");
for(var i=0;i<pAry.length;i++){
(function (i) {
pAry[i].οnclick= function () {
alert(i);
}
})(i);
}
}
init();
闭包的概念:
有权访问另一个函数作用域内的变量的函数叫做闭包。闭包有以下几个作用:
(1)匿名自执行函数。匿名自执行函数是一个闭包,函数执行完后会立刻释放资源,不污染全局对象
(2)结果缓存。闭包可以保留函数内部的值,当第二次调用的时候就会从缓存中读取该对象
(3)封装
(4)实现类和继承