# 闭包 Closure
有权访问其他函数作用域中变量的函数
最简单的方式,在另一个函数内定义一个函数
# 理解作用域
var a = 1;
function f1() {
var a = 2;
function f2() {
var a = 3;
console.log(a);
}
}
f1();
// undefined
由于f1里没有 return f2,这里只是声明了f2,没有调用,所以输出 undefined
让内部函数执行的几种方式:
- 先声明f2,执行 f1 时调用了 f2,输出 3
var a = 1;
function f1() {
var a = 2;
f2();
}
function f2() {
var a = 3;
console.log(a);
}
f1();
// 3
- 直接添加返回值
function f1() {
var a = 2;
function f2() {
console.log(a);//2
}
return f2;
}
var x = f1();
x();
- 不返回函数,给 f3 赋值。先执行 f1(),再执行 f3()。
var f3;
function f1() {
var a = 2;
f3 = function() {
console.log(a);
}
}
f1(); // undefined
f3(); // 2
# 执行上下文 Execution context
执行上下文类型:
- 全局执行上下文
- 函数执行上下文
- eval执行上下文
执行栈:后进先出
创建执行上下文:
- this绑定
- 创建词法环境: let const
- 创建变量环境: 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谈谈你对闭包的理解