一;首先明确执行上下文:
执行上下文包括:
1.全局执行上下文(全局作用域):
当我们启动程序时,我们从全局执行上下文中开始。一些变量是在全局执行上下文中声明的。我们称之为全局变量。
2.本地执行上下文(函数作用域):
当代码执行到函数时,会创建一个新的执行上下文,称之为本地上下文或函数上下文,这个本地执行上下文将有它自己的一组变量,这些变量将是这个执行上下文的本地变量。
当一个函数被执行完成之后:
-
这个本地执行上下文从执行堆栈中弹出。
-
函数将返回值返回调用上下文。调用上下文是调用这个本地的执行上下文,它可以是全局执行上下文,也可以是另外一个本地的执行上下文。这取决于调用执行上下文来处理此时的返回值,返回的值可以是一个对象、一个数组、一个函数、一个布尔值等等,如果函数没有
return
语句,则返回undefined
。 -
这个本地执行上下文被销毁,销毁是很重要,这个本地执行上下文中声明的所有变量都将被删除,不在有变量,这个就是为什么 称为本地执行上下文中自有的变量。
二:闭包是怎么产生的以及闭包是什么?
无论何时,当声明函数并将其赋值给变量时,该变量都要存储函数定义和闭包,闭包包含声明(创建)这个函数时所处上下文(作用域)的全部变量。它类似于背包。函数定义附带一个小背包,它的包中存储了函数定义创建时作用域中的所有变量。
当我们函数返回函数时,就需要额外注意;
比如用一个变量调用一个函数,该函数的返回值为函数时:
1: function createCounter() {
2: let counter = 0
3: const myFunction = function() {
4: counter = counter + 1
5: return counter
6: }
7: return myFunction
8: }
9: const increment = createCounter()
10: const c1 = increment()
11: const c2 = increment()
12: const c3 = increment()
13: console.log('example increment', c1, c2, c3)
而当我们再次调用这个由 调用函数返回的函数时,当遇到该函数作用域不存在的变量时,它会先去自己的闭包当中寻找,如果找不到的话就会向上层作用域中查找,知道找到全局作用域结束。
注意:
在全局作用域时将函数声明并赋值给一个变量的时候也会产生闭包,但该闭包是在全局作用域当中产生的,所以它可以访问全局变量,所以在全局作用域中闭包的概念并不重要。
但是当出现函数返回函数的情况时,闭包的概念就很重要。
闭包的本质:
本质就是上级作用域内变量的生命周期,因为被下级作用域内引用,而没有被释放。就导致上级作用域内的变量,等到下级作用域执行完以后才正常得到释放。
闭包的作用:
1.保护函数的私有变量不受外部干扰。
2.形成不被销毁的栈内存。
3.将上级作用域的引用保存下来,实现方法或属性的私有化。