闭包

33 阅读2分钟

闭包

预编译

理解闭包需要理解为什么一个函数到底能访问到哪些变量

这个取决于词法作用域,又被称为静态作用域,决定了变量和函数的可见性是由其在源码的位置

函数每次调用所使用的执行上下文(EC)

执行上下文生命周期 = 创建阶段(Compilation) + 执行阶段(Execution)

创建阶段中 预编译会执行:

  1. 建立变量对象VO(variable Object)

    1. 根据实参创建形参,若是没有就是undefined
    2. 将function声明挂载,值指向函数体,同名进行覆盖
    3. 将var声明挂载,值为undefined,执行阶段执行赋值
  2. 确定作用域链[[Scope]]

    1. 函数定义时就确定了函数作用域 img
  3. 确定this绑定

闭包

闭包源于词法作用域的规则,只有在作用域小于或等于闭包定义位置的函数才能访问到这个变量,简而言之,当一个内部函数可以访问到其外部函数的变量的情况,称之为闭包,特别来说,当这个内部函数仍然能被使用的情况下,即使外部函数已经失去访问,其内部变量仍然能被访问,所以V8回收机制不会进行销毁,但又不会被其他函数访问,实现了一定的私有性。

var age=20
const baz = function () {
    var name= '大仙'
    function bar() {
        console.log(count,age)
    }
​
    var count =1
    var age =18
    return bar
}()
baz()
​

外层函数即使已销毁,其 LexicalEnvironment 仍被内层函数 [[Scope]] 引用,因此内层函数每次执行同样会新建自己的 EC,但外层环境记录是复用同一份堆对象,不会重新创建。

作用

  • 实现共有变量(私有性)
  • 缓存数据
  • 封装模块,防止全局变量污染