深入理解JavaScript系列(6):执行上下文
在《深入理解 JavaScript 系列(2):执行上下文栈》中提到,当 JavaScript 代码执行代码时,就会创建一个执行上下文。
对于执行上下文,都有三个重要属性:
- 变量对象 (Variable Object - VO)
- 作用域链
- this
分别单独介绍了三个属性 - 《深入理解 JavaScript 系列(3):变量对象》、《深入理解 JavaScript 系列(4):作用域链》、《深入理解 JavaScript 系列(5):this》。
我们在上面的文章中,不止一次提到过执行上下文这个东西,然后每次都是分开介绍的,并不完全,现在我们就来整合一下执行上下文吧。
执行上下文 - 例子一
我们直接给出一个例子吧,然后来看看什么是执行上下文吧。
1 | var name = 'hzq'; |
执行过程
1. 执行全局代码,创建全局上下文,并压入执行上下文栈
1 | ECStack = [globalContext]; |
2. 全局上下文初始化,同时创建 checkName
函数,保存作用域链到函数内部属性 [[scope]]
1 | globalContext = { |
3. 执行 checkName 函数,创建函数上下文,并压入栈
1 | ECStack = [checkNameContext, globalContext]; |
4. checkName 函数执行上下文初始化: | 这时候 fn
函数也被创建,保存 [[scope]]
- 复制函数
[[scope]]
属性 - arguments 创建活动对象
- 初始化活动对象,加入形参、函数声明、变量声明
- 将活动对象压入函数作用域链顶端
1 | checkNameContext = { |
5. 执行 fn
函数,创建上下文,压入栈
1 | ECStack = [fnContext, checkNameContext, globalContext]; |
6. fn
函数执行上下文初始化
1 | fnContext = { |
7. fn
通过作用域链查找 name
属性,并返回
8. fn 函数指向完毕,出栈
1 | ECStack = [checkNameContext, globalContext]; |
9. checkName
函数执行完毕,出栈
1 | ECStack = [globalContext]; |
10. 继续执行其他全局代码,直到其他代码执行完毕,全局上下文出栈
执行上下文 - 例子二
1 | var name = 'hzq'; |
执行过程 - 变化点
我们直接来看看例子二与例子一的不同点。
5. checkName
函数执行完毕,出栈
1 | ECStack = [globalContext]; |
6. 执行 fn
函数,创建上下文,压入栈
1 | ECStack = [fnContext, globalContext]; |
7. fn
函数执行上下文初始化
1 | fnContext = { |
8. fn
函数执行完毕,出栈
9. 执行全局其他代码,执行完毕,全局上下文出栈
是不是很简单呢?
相关文章推荐
-------------------- 本文结束
感谢阅读 --------------------