美文网首页
闭包再深入

闭包再深入

作者: hellowade | 来源:发表于2017-08-30 14:41 被阅读0次

    一直对闭包这个概念模糊不清,今天捣鼓半天,大致理通了。
    闭包是什么?

    有权访问另外一个函数作用域中的变量的函数。

    一般来讲,作用域是由函数创建的(这里我们只讨论函数作用域,不涉及ES6之后的块级作用域)。每个函数的作用域都是封闭的,外部是无法访问函数作用域中的变量。
    那有没有办法可以从外部访问到函数内部的变量呢
    答案是有的,通过嵌套函数的方式,见下面的示例。

    function change(){
        var a = 1
        function plus(){
            a++
            console.log(a)
        }
        return plus
    }
    var final = change()
    final() //2
    final() //3
    final() //4
    

    在该例中,我们得增加点知识点:

    • 函数的作用域
    • 变量的生命周期

    plus函数作用域内没有变量a,依据作用域链,找到父作用域中的变量a,当执行final()时,a++,a=2。再执行final()时,结果依然+1。
    这里有点困惑,变量的生命周期起始于函数执行时,终止于函数执行完毕,为什么这里面函数中的变量a未被回收,数值一直递增。
    原因在于变量a被函数plus引用,final()间接引用着变量a。导致变量a未被内存回收。
    闭包最大的用处在于:暴露局部变量,保持变量在内存中不被回收。
    再来看些经典的闭包题来理解下思路

    for(var i = 1; i< 10; i++){
        function a(){
        console.log(i)
        }
    } 
    a() //10
    

    为什么得到10,很简单。for循环中是函数表达式,当循环结束后,执行a(),其中的i不存在按作用域链找到上一级的i并引用,结果为10。
    怎么让其按我们设想的0,1,2...输出呢?
    也很简单,每次循环执行一次函数,传参,var a = i ,运用立即执行函数,见下

    for(var i = 1; i< 10; i++){
        !function a(a){
        console.log(a)
        }(i)
    } 
    

    如果纠结0~9,和输出来为什么是10,可以参考下for循环的执行次序

    相关文章

      网友评论

          本文标题:闭包再深入

          本文链接:https://www.haomeiwen.com/subject/cchtjxtx.html