首页 > 代码库 > javascript闭包浅析

javascript闭包浅析

何为闭包;

闭包跟作用域相关的,ECMAScript 允许使用内部函数,即函数定义和函数表达式位于另一个函数的函数体内。内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

确实有点晕看个例子吧

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style>
li{
height:30px;
background: red;
margin:10px;
}
</style>
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</body>
<script>
var lis = document.getElementsByTagName(‘li‘)
for (var i = 0; i <= lis.length; i++){
lis[i].onclick = function(num){
return function(){
alert(num);
}
}(i);
}
</script>
</html>

上面的例子,要给li[i]绑定点击事件,点击的时候弹出i值(i值即索引值,也就是当前是第几个li的意思啦)。如果上面没有使用闭包函数,而是直接写成(只写了js代码):

<script>
var lis = document.getElementsByTagName(‘li‘)
for (var i = 0; i <= lis.length; i++){
lis[i].onclick = function(){
alert(i)
}
}
</script>

此时弹出的i值变成i的最大值。原因:JS在函数执行之前的预编译期就把i值给循环一遍了,也就是i值已经不是我们过去认识的i值了。所以我们就通过闭包函数,把每一步循环的i值给保存一下,传递进去内部函数去执行新的语句。
但是有一点必须要注意的是:闭包使函数作用域处于持续被引用的状态,不能够自动释放。只能手动清除,或者只能在浏览器窗口被关闭时才会清除占用空间,因此对于内存有一定的损耗,不推荐经常使用。
 
闭包应用实例(tab切换效果):

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<style>
*{
margin:0;
padding:0;
}
ul{
margin:0;
list-style: none;
}
#tit li{
float:left;
width:90px;
height:40px;
}
.tit{
background: red;
}
.select{
background:gray;
}
#con div{
width:270px;
line-height:300px;
border:1px solid red;
font-size:50px;
color:red;
text-align:center;

}
.con{
display:none;
}
.show{
display:block;
}
</style>
<body>
<ul id="tit">
<li class="tit select">1</li>
<li class="tit">2</li>
<li class="tit">3</li>
</ul>
<div id="con">
<div class="con show">1</div>
<div class="con">2</div>
<div class="con">3</div>
</div>
</body>
<script>
var tits = document.getElementById(‘tit‘).getElementsByTagName(‘li‘),
cons = document.getElementById(‘con‘).getElementsByTagName(‘div‘);

for (var i = 0, len = tits.length; i < len; i++){
tits[i].onclick = function(i){
// 利用闭包函数去实现i值的传递
return function(){
// 进行for循环,初始化类名
for (var j = 0,len = cons.length; j < len; j++){
tits[j].className = ‘tit‘;
cons[j].className = ‘con‘;
}
tits[i].className = ‘select‘;
cons[i].className = ‘show‘;
}
}(i);
}
</script>
</html>