# 闭包 Closure

有权访问其他函数作用域中变量的函数

最简单的方式,在另一个函数内定义一个函数

# 理解作用域

var a = 1;

function f1() {
  var a = 2;
  function f2() {
    var a = 3;
    console.log(a);
  }
}

f1();
// undefined

由于f1里没有 return f2,这里只是声明了f2,没有调用,所以输出 undefined

让内部函数执行的几种方式:

  1. 先声明f2,执行 f1 时调用了 f2,输出 3
var a = 1;

function f1() {
    var a = 2;
    f2();
}

function f2() {
    var a = 3;
    console.log(a);
}

f1();
// 3
  1. 直接添加返回值
function f1() {
  var a = 2;
  function f2() {
    console.log(a);//2
  }
  return f2;
}

var x = f1();
x();
  1. 不返回函数,给 f3 赋值。先执行 f1(),再执行 f3()。
var f3;

function f1() {
    var a = 2;
    f3 = function() {
        console.log(a);
    }
}

f1(); // undefined
f3(); // 2

# 执行上下文 Execution context

执行上下文类型:

  • 全局执行上下文
  • 函数执行上下文
  • eval执行上下文

执行栈:后进先出

创建执行上下文:

  1. this绑定
  2. 创建词法环境: let const
  3. 创建变量环境: var
var a = 1;

function f1() {
  var a = 2;
  
  function f2() {
    var a = 3;
    console.log(a);
  }
  
  return f2;
}

全局执行上下文和函数执行上下文的伪代码表示:

// 全局执行上下文
GlobalExecutionContext = {
    // 绑定this
    ThisBinding: <GlobalObject>, 
    
    // 词法环境
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Object", // 对象环境记录器
            // 绑定标识符
            f1: <func>
        },
        
        // 外部环境的引用
        outer: <null>
    }, 
    
    // 变量环境
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Object",
            // 绑定标识符
            a: undefined
        },
        outer: <null>
    }  
}

// 调用函数 f1 时,创建函数执行上下文
OuterFunctionExecutionContext = {
    ThisBinding: <GlobalObject>,
        
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative", // 声明式环境记录器
            f2: <func>
        },
        outer: <GlobalLexicalEnvironment>
    },
        
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            a: undefined
        },
        outer: <GlobalLexicalEnvironment>
    }
}

// 调用函数 f2,创建内部函数执行上下文
InnerFunctionExecutionContext = {
    ThisBinding: <OuterFunction>,
    
    LexicalEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            
        },
        outer: <OuterFunctionLexicalEnvironment>
    },
    
    VariableEnvironment: {
        EnvironmentRecord: {
            Type: "Declarative",
            a: undefined
        },
        outer: <OuterFunctionLexicalEnvironment>
    }
}

# 参考资料

神三元的博客:004谈谈你对闭包的理解

理解 JavaScript 中的执行上下文和执行栈

Last Updated: 6/5/2020, 9:50:33 PM