对于闭包的理解

 


、变量提升

1. JS代码运行机制:分段预编译 → 逐行执行。

2. 预编译阶段可能存在【变量提升】的情况,将【变量声明的语句】提升至作用域顶端(不包括【变量赋值的语句】)。

3. var声明变量时,变量自动初始化为undefined;const和let声明变量时,变量不会自动初始化,只有在代码执行阶段,遇到赋值操作时,才会被初始化。


4. function声明函数时,整个函数体得到提升。


5. class声明类时,不存在提升。


、作用域

1. 全局作用域

2. 函数作用域

3. 块级作用域:{...}大括号内的代码块

   ① 只有使用const和let声明变量时,会针对这个变量形成一个封闭的块级作用域。

   ② 声明变量前访问该变量,会提示ReferenceError(块级作用域外 !!! 更正: 这里也属于块级作用域内);声明变量后访问该变量,可正常运行(块级作用域内)。

   ③ 暂时性死区,temporal dead zone:起始于函数开始!!! 更正: 起始于块级作用域开始,比如if的{},终止于相关变量声明。


三、调用栈

1. 作用域是在预编译阶段确定的;作用域链是在函数调用后,执行上下文创建后,才确定的。

2. 执行上下文包括:变量对象、作用域链、this。

3. 调用栈:管理执行上下文的栈(管理函数调用关系的栈)。

4. 函数被调用 → 入栈 → 函数执行 (可访问其内部变量) → 函数执行完毕 → 出栈 (该函数的执行上下文被销毁)


四、闭包

1. 嵌套函数中,内层函数引用了外层函数作用域下的变量。

2. 外层函数执行结束,上下文被销毁,但被内层函数引用的变量不会消失。

3. 开发者仍可通过调用内层函数来访问外层函数中的该变量。

4. 内层函数及其捆绑的外层函数变量的引用,被称为闭包。



五、内存管理

1. 内存空间 = 栈空间 + 堆空间

2. 基本类型数据保存在栈空间中;引用类型数据保存在堆空间中,其地址值保存在栈空间中。

3. 注意避免内存泄漏。

   常见情况:addEventListener - removeEventListener、setInterval - clearInterval。

4. 闭包使用不当,易引发内存泄漏。可在浏览器控制台Memory(内存)标签页内展开调查。

评论