作用域和闭包的通俗理解(3)

functionfn3() {
        var a = 3
        var fun4 = function () {  //fun4采用的是“函数表达式”创建的函数,此时内部函数的声明并没有提前
            console.log(a)
        }
    }

fn3();

常见的闭包

将一个函数作为另一个函数的返回值

将函数作为实参传递给另一个函数调用。

闭包1:将一个函数作为另一个函数的返回值

functionfn1() {
      var a = 2

functionfn2() {
        a++
        console.log(a)
      }
      return fn2
    }

var f = fn1();  //执行外部函数fn1,返回的是内部函数fn2
    f() // 3      //执行fn2
    f() // 4      //再次执行fn2

当f()第二次执行的时候,a加1了,也就说明了:闭包里的数据没有消失,而是保存在了内存中。如果没有闭包,代码执行完倒数第三行后,变量a就消失了。

上面的代码中,虽然调用了内部函数两次,但是,闭包对象只创建了一个。

也就是说,要看闭包对象创建了一个,就看:外部函数执行了几次(与内部函数执行几次无关)。

闭包2. 将函数作为实参传递给另一个函数调用

functionshowDelay(msg, time) {
      setTimeout(function() {  //这个function是闭包,因为是嵌套的子函数,而且引用了外部函数的变量msg
        alert(msg)
      }, time)
    }
    showDelay('atguigu', 2000)

上面的代码中,闭包是里面的funciton,因为它是嵌套的子函数,而且引用了外部函数的变量msg。

闭包的作用

作用1. 使用函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期)

作用2. 让函数外部可以操作(读写)到函数内部的数据(变量/函数)

我们让然拿这段代码来分析:

functionfn1() {
      var a = 2

functionfn2() {
        a++
        console.log(a)
      }
      return fn2
    }

var f = fn1();  //执行外部函数fn1,返回的是内部函数fn2
    f() // 3      //执行fn2
    f() // 4      //再次执行fn2

作用1分析

上方代码中,外部函数fn1执行完毕后,变量a并没有立即消失,而是保存在内存当中。

作用2分析:

函数fn1中的变量a,是在fn1这个函数作用域内,因此外部无法访问。但是通过闭包,外部就可以操作到变量a。

达到的效果是:外界看不到变量a,但可以操作a

比如上面达到的效果是:我看不到变量a,但是每次执行函数后,让a加1。当然,如果我真想看到a,我可以在fn2中将a返回即可。

回答几个问题:

问题1. 函数执行完后, 函数内部声明的局部变量是否还存在?

答案:一般是不存在, 存在于闭中的变量才可能存在。

闭包能够一直存在的根本原因是f,因为f接收了fn1(),这个是闭包,闭包里有a。注意,此时,fn2并不存在了,但是里面的对象(即闭包)依然存在,因为用f接收了。

问题2. 在函数外部能直接访问函数内部的局部变量吗?

不能,但我们可以通过闭包让外部操作它。

闭包的生命周期

产生: 嵌套内部函数fn2被声明时就产生了(不是在调用)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/9fd4a7fc9889b57ba35c4e35b4b01968.html