闭包
预编译
理解闭包需要理解为什么一个函数到底能访问到哪些变量
这个取决于词法作用域,又被称为静态作用域,决定了变量和函数的可见性是由其在源码的位置
函数每次调用所使用的执行上下文(EC)
执行上下文生命周期 = 创建阶段(Compilation) + 执行阶段(Execution)
创建阶段中 预编译会执行:
-
建立变量对象VO(variable Object)
- 根据实参创建形参,若是没有就是undefined
- 将function声明挂载,值指向函数体,同名进行覆盖
- 将var声明挂载,值为undefined,执行阶段执行赋值
-
确定作用域链[[Scope]]
- 函数定义时就确定了函数作用域
- 函数定义时就确定了函数作用域
-
确定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,但外层环境记录是复用同一份堆对象,不会重新创建。
作用
- 实现共有变量(私有性)
- 缓存数据
- 封装模块,防止全局变量污染