理解闭包经典例子

闭包,很多人对它的定义和理解都不一样,关于它的文章比比皆是,但是要真正意义上的理解它,还是有些难度的。对于闭包的定义,我也不敢妄下定论,所以这篇文章只是提及关于闭包的几个经典例子。
现阶段,我对于闭包的理解为:闭包是定义在一个函数内的另一个函数,这个函数可以访问外层函数中的局部变量,并将这个函数作为返回值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值

我们先来看一段代码

  • 1
  • 2
  • 3
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的顺序值。

你可能感兴趣的:(理解闭包经典例子)