JS闭包的实现与缺陷解决办法
总所周知局部变量(函数变量)在外部不能直接访问,但有需求要它在全局访问而又不定义为全局变量,这里就需要使用到闭包。
闭包的实现
例如使用js想要实现点击一下计数器加一的效果。可以用如下代码实现。
<button type="button" onclick="add()">计数</button>
<div id="div">0</div>
<script>
var count = 0;
function add(){
document.getElementById("div").innerHTML = ++count;
}
</script>
这样把计数变量count存放在全局中虽然能够实现,但有一个隐患是除了add函数可以改变count的值其他也同样能直接改变。那么将count定义在add函数中的变量,它成为局部变量后外部访问不到,只需将add函数返回(return)count自增的代码并返回增加后的count就可以了。代码如下:
<button type="button" onclick="Adds()">计数</button>
<div id="div">0</p>
<script>
var add = (function () {
var count = 0;
return function () {
counter ++;
return count;
}
})();
function Adds(){
document.getElementById("div").innerHTML = add();
}
</script>
缺陷的产生与解决办法
如下例题,我想点击某一个按钮返回按钮存在获取元素中的下标
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<script>
var btns = document.getElementsByTagName('button');
for(var i = 0 ;i<btns.length ; i++){
btns[i].onclick = function(){
console.log(i);
}
}
</script>
初略看来该代码可以实现点击某一个按钮返回该按钮存在获取元素中的下标,但结果是点击任意一个都是返回4。原因是点击前代码已经执行完循环了,这时相当于给每个按钮绑定了点击事件返回i的值,但此时i是循环执行完后的i(为4),所以点击任意按钮为4,这就是闭包函数形成所带来的缺陷,为解决此问题。只需将for循环中的代码块改为立即执行函数,这样循环的每一次将i值赋给立即执行函数执行就可以达到想要的效果了。
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<script>
var btns = document.getElementsByTagName('button');
for(var i = 0 ;i<btns.length ; i++){
(function(){
btns[i].onclick = function(){
console.log(i);}
}
)(i);
}
</script>