执行上下文的生命周期包括三个阶段:创建阶段→执行阶段→回收阶段。执行上下文它分为:
- 1.全局上下文。打开浏览器,你就已经将全局上下文压进了执行栈。所以全局上下文永远位于执行栈的栈底,只有当你关闭浏览器,他才会出栈
- 2.函数上下文。当执行一个函数时,进入了创建阶段:
1.创建变量对象:首先初始化函数的参数arguments,提升函数声明和变量声明。
2.创建作用域链
3.确定this指向
其中第2步创建了作用域链。作用域链的目的,就是让当前上下文能够访问到执行栈中在它下面的其他上下文,如全局上下文。
作用域链有方向性,也就是位于顶端的上下文能够沿着链访问底部的。而全局上下文位于最下面,所以所有的其他上下文必然能访问全局上下文的变量等。
根据上面的观点,只有当包含某个变量的上下文存在时,这个变量才能被访问。如果包含该变量的上下文被销毁,该变量无法再被访问。但按照栈的特点,这种情况不会存在,因为作用域链具有方向性(沿着栈底方向),如果要访问的上下文已被销毁,自身也应该被销毁了。但有个东西叫闭包。
闭包
var getAge = (function(){var age = 11; return function() {return age}})()
age还能访问 但是该立即执行函数已经出栈
age这个值其实是存储在堆空间的。
getAge应该维持着对该堆空间的引用(地址)
打印getAge.prototype
{constructor: ƒ}
constructor: ƒ ()
arguments: null
caller: null
length: 0
name: ""
prototype: {constructor: ƒ}
[[FunctionLocation]]: VM603:1
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[2]
[[Prototype]]: Object
发现了一个JS引擎才能访问的属性
Scopes
0: Closure
age: 11
发现age就在这里