老司机也会在闭包相关知识点翻车
image.png

基本知识

作用域

作用域其实就是一套规则:这个规则 用于确定在特定场景下如何查找变量

函数作用域和全局作用域

总结一下 :在 JavaScript 执行一段函数时,遇见变量读取其值,这时候会“就近”先在函数内部找该变量的声明或者赋值情况。这里涉及“变量声明方式”以及“变量提升”的知识点。

块级作用域和暂时性死区

image.png
image.png

  1. function foo(arg1 = arg2, arg2) {
  2. console.log(`${arg1} ${arg2}`)
  3. }
  4. foo(undefined, 'arg2')
  5. // Uncaught ReferenceError: arg2 is not defined
  6. foo(null, 'arg2')

因为除了块级作用域以外,函数参数默认值也会受到 TDZ 影响。

  1. function foo(arg1) {
  2. let arg1
  3. }
  4. foo('arg1')

实际上会报错:Uncaught SyntaxError: Identifier ‘arg1’ has already been declared。这同样跟 TDZ 没有关系,而是因为函数参数名会出现在其“执行上下文/作用域”当中。
image.png

执行上下文和调用栈

执行上下文

代码执行的两个阶段
  • 代码预编译阶段
  • 代码执行阶段

结论 作用域在预编译阶段确定,但是作用域链是在执行上下文的创建阶段完全生成的。因为函数在调用时,才会开始创建对应的执行上下文。执行上下文包括了:变量对象、作用域链以及 this 的指向
image.png

调用栈

闭包

image.png
我们知道正常情况下外界是无法访问函数内部变量的,函数执行完之后,上下文即被销毁。但是在(外层)函数中,如果我们返回了另一个函数,且这个返回的函数使用了(外层)函数内的变量,外界因而便能够通过这个返回的函数获取原(外层)函数内部的变量值。这就是闭包的 基本原理

内存管理