理解闭包

前面的文章曾经说到过闭包的问题,参见《闭包导致的问题》,今天回头看看,并没有介绍到闭包,仅仅提到了闭包的概念而已。

首先我们得理解在javascript中,什么是闭包?

谈到闭包,就必然要涉及变量,在javascript中,变量一般分为全局变量和局部变量。从我的角度(初学者角度)来理解的话,其实闭包的主要作用在于封装变量为局部变量,减少到全局作用域的污染。

那么,究竟什么是闭包呢?

function outer (){
     //  定义一些变量
    function inner(){
    //  内部函数执行代码块
    }  
}

从上面的代码来理解闭包的定义,如果要产生闭包的效果,就必须能够在outer外部调用到inner,放在后面再说,这里仅仅理解闭包的概念。

outer函数定义了一个作用域,在这个作用域内声明了函数inner,函数inner能够影响到的范围,或者说可以调用到的变量所在的区域(当然也能引用到全局作用域变量),就是inner闭包。

用一张图片来描述的话,红色边框表示该函数的作用域范围,而里面的半透明填充色即为外部函数的内部声明函数的闭包范围,其实闭包就相当于父函数的作用域。

当我们将inner函数传递到outer函数外部调用的时候,就产生了闭包,这个闭包其实就是outer函数的作用域,这样,就能够全部定义局部变量,从而减少全局变量的定义。

再举一个闭包常见的例子:循环遇到定时器,或者事件处理函数,这里举定时器的例子。

    function foo() {
        for (var i = 0; i < 3; i++) {
          setTimeout(function () {
              console.log(i);
          }, 1000);
        }
      }
      foo();

打开控制台可以看到,会打印三个3出来,而不是我们所期望的相隔1秒,分别打印0,1,2。

这里其实就是当执行到延迟定时器内部函数块console.log(i)时,循环已经结束,此时i=3,而不是延迟定时器在执行时,分别创建作用域,所以这里必然结合闭包,给每次循环单独创建一个作用域,

    function foo() {
        for (var i = 0; i < 3; i++) {
          (function (i) {
            setTimeout(function () {
                console.log(i)
            }, 1000);
          })(i);
        }
      }
      foo();

如此,就能实现相隔1秒分别打印0,1,2。

只要理解了闭包的概念,再去看各种涉及到闭包的例子,应该比较容易理解javascript中的痛点--闭包--了。

原文地址:https://www.cnblogs.com/zhuhuoxingguang/p/6400217.html