执行上下文包括:
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.将上级作用域的引用保存下来,实现方法或属性的私有化。