美文网首页
彻底理解闭包

彻底理解闭包

作者: 一肩月光 | 来源:发表于2017-03-19 18:15 被阅读38次
    yellow

    理清定义

    执行环境(execution context):定义了变量或函数有权访问的其他数据。每个执行环境对应一个「变量对象」。

    变量对象(variable object):包含当前能够访问的所有变量、函数总和。即是 this 所代指的内容。

    作用域链:本质是一个指向变量对象的指针表,当代码被执行时就会被创建,包含有序的变量对象。(自己可以理解为一个数组[当前变量对象,上一级变量对象……全局变量对象])

    活动对象(activation object):当代码进入一个环境,而此环境是一个函数时,则变量对象 = 活动变量,初始包含 arguments 对象,传入的参数变量。

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

    实例分析

    闭包的本质是什么?
    当某个函数被调用,创建一个执行环境(execution context)及作用域链,重点是,此时闭包的作用域链包含了外部函数的活动变量,由于存在引用,内存不会回收外部函数的活动变量,直到闭包被销毁。

    function outer() {
      var private_val_1 = { val: 1 },
        private_val_2 = { val: 2 }
    
      function inner() {
        var inner_val_1 = private_val_1
    
        console.log(private_val_2)
      }
    
      return inner
    }
    
    var closure = outer()
    
    closure() // { val: 2 }
    

    由于 inner 函数的作用域链中,包含了 outer 函数的活动对象的索引,所以在执行 inner 函数时,会从 inner 函数 [[Scope]] 属性中,读取类似这样的一份指针列表

    [outer 变量对象的引用,window 变量对象的引用]
    
    1. 创建一个执行环境
    2. 复制 [[Scope]] 中指向对象,构建作用域链
    3. 创建 inner 的活动对象(=变量对象)推至作用域链的顶端
    4. 访问某个变量,从作用域链中搜索
    5. 执行结束,移除执行环境,销毁局部活动对象。

    反观 outer 函数执行过程,在最后一步,由于 outer 活动对象在 inner 函数的 [[Scope]] 被引用,不能被销毁,如此闭包产生。

    推荐阅读:深入理解JS中声明提升、作用域(链)和this关键字

    相关文章

      网友评论

          本文标题:彻底理解闭包

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