闭包,很多人对它的定义和理解都不一样,关于它的文章比比皆是,但是要真正意义上的理解它,还是有些难度的。对于闭包的定义,我也不敢妄下定论,所以这篇文章只是提及关于闭包的几个经典例子。
现阶段,我对于闭包的理解为:闭包是定义在一个函数内的另一个函数,这个函数可以访问外层函数中的局部变量,并将这个函数作为返回值return出去。
计时器
题目:定义一个定时器,计算点击网页的次数
这个题目非常简单,想必大家都能写出来。
var count = 0;
function addCount() {
count++;
}
document.body.addEventListener("click", addCount);
count作为一个全局变量,其他地方都可以对它进行操作,如果其他地方对count重新赋值或者重新定义count,那么这个计时器就被破坏了。这时候,闭包就起作用了。
function addCount() {
var count = 0;
var addCount = function() {
count++;
}
return addCount;
}
document.body.addEventListener("click", addCount);
将count作为一个局部变量,把addCount作为函数返回,这样,其他地方对count进行赋值或者重新定义,对计时器也不会有影响了。
for循环中的i值
我们先来看一段代码
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function() {
console.log(i);
}
}
运行这段代码后,大家或许会有疑问,为什么点击任一个li标签,console台打印的都是3。
代码运行结束后,给每个li标签定义了click函数,但这个函数没有立即执行,只有当点击li时,才会执行该click函数;当点击li执行函数时,函数中的变量i没有在函数中定义,根据js的作用域链原则,会继续向上级作用域查询,因此找到了全局作用域中的i,这时for循环已经执行结束,此时全局作用域中的i已经变为了3,故打印出来的当然是3了。
要想实现,打印出来的值为点击li的顺序值,这时,闭包又起到了作用
var lis = document.getElementsByTagName("li");
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = (function(i) {
var clickLi = function() {
console.log(i);
}
return clickLi;
})(i)
}
在for循环执行时,立即将当前的i值作为形参传入clickLi中,而形参默认为函数内的局部变量,函数外部是不能对i进行操作的。所以,当点击li时,执行clickLi函数时,打印出来的则是li的顺序值。
网友评论