JS的函数内部可以访问全局变量,但是在函数的外部是不可以读取内部的局部变量
闭包其实就是提供一个方式来读取函数内部的变量

简要说明

  • 单纯的觉得闭包是拿到函数内部的变量是不对的,以下这种方式也可以拿到,但它不是闭包

    // 外部可以拿到a,但不是闭包
    (function f1(){
        let a = 10
        (function f2(){
            alert(a)
        }())
    })()
    
    function f3(){
        let a =100
        return a
    }
    f3()//101
    f3()//101   此时函数f3已经被垃圾回收了,再次调用就是重新开始创建变量等一系列的过程
  • 闭包真正的原因是局部变量无法长久保存,全局变量又容易污染环境,希望可以找到一种既可以长久保存又不会造成全局污染的方法,这就是闭包的机制。所以看似代码复杂化,其实大有来头。

    function f1(){
        let a = 100
        function f2(){
            a++
            console.log(a)
        }
        return f2
    }
    let f = f1 // f1执行的结果,其实就是return出来的f2函数 ===== 闭包
    f() // 101
    f() // 102
    /**
     * 1、f1的调用结果被赋给了全局变量f,全局变量f一直存在于内存中,f1函数执行完毕之后就会被释放,但是return出来了一个函数,也就是会造成内存泄漏的原因(变量a没有被释放)
     * 2、a是局部变量但是他不会被销毁。因为f2还保持着对a的引用(JS的垃圾回收机制之中的引用计数原则)
    */

    用匿名函数简写

    function f1(){
        let a = 100
        return function(){
            a++
            console.log(a)
        }
    }
    let f = f1()
    f()
    f()

    总结

  1. 注意全局变量一直存在于内存中,局部变量执行完之后被垃圾回收(包括函数),再次执行该函数的时候又得重新开始
  2. 闭包的代码复杂的真正原因
    function f1(){
        let a = 0
        return function(){
            a++
        }
    }
    let s1 = f1()
    let s2 = f1()
    s1()//1
    s1()//2
    s2()//3