# 深入执行上下文、词法环境、变量环境
# 执行上下文的概念
什么是执行上下文
javascript 代码解析和执行时所在的环境
# 执行上下文的类型
# 全局执行上下文
- 浏览器环境中全局对象是
window
, 在node环境中全局对象是global
- js代码开始运行后。首先进入全局执行上下文环境中,不在任何函数中的js代码都会在全局执行上下文中
- 一个js程序中只存在一个全局执行上下文。创建时会压人栈底,只有当程序结束时才会弹出
- 全局执行上下文会做两件事。1.创建全局对象,2.将this指向这个全局对象
# 函数执行上下文
- 函数每次调用都会产生一个新的函数执行上下文,每个函数都拥有自己的执行上下文,但是只有调用的时候才会被创建
- 函数执行上下文的生命周期分为两个阶段。创建和执行
- 每一个执行上下文中都有以下三个属性
- 作用域链 scope chain
- VO变量对象 // variableObject -> 初始化变量、函数、形参等
- this
# Eval执行上下文
eval函数执行时产生的执行上下文。
# 执行上下文栈
- 首先创建全局执行上下文, 压入栈底
- 每当调用一个函数时,创建函数的函数执行上下文。并且压入栈顶
- 当函数执行完成后,会从执行上下文栈中弹出,js引擎继续执栈顶的函数。
function fun1(){
console.log('func1')
fun2()
}
function fun2(){
console.log('func2')
}
fun1()
/*
* fun2
* fun1 fun1 fun1
* global => global => global => global => global
*/
# 执行上下文生命周期
# 变量对象VO和活动对象AO
变量对象VO
VO 对应的是函数创建阶段,JS 解析引擎进行预解析时,所有的变量和函数的声明,统称为 Variable Object。该变量与执行上下文相关,知道自己的数据存储在哪里,并且知道如何访问。VO 是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容:
- 变量 (var, 变量声明)
- 函数声明
- 函数的形参
function add(a, b) {
var sum = a + b;
function say() {
alert(sum);
}
return sum;
}
// sum,say,a,b 组合的对象就是VO,不过该对象的值基本上都是undefined
活动对象(AO)
AO 对应的是函数执行阶段,当函数被调用执行时,会建立一个执行上下文,该执行上下文包含了函数所需的所有变量,该变量共同组成了一个新的对象就是 Activetion Object。该对象包含了:
- 函数的所有局部变量
- 函数的所有命名参数
- 函数的参数集合
- 函数的 this 指向
function add(a, b) {
var sum = a + b;
function say() {
alert(sum);
}
return sum;
}
add(4, 5);
// JS对象来表示AO
// AO = {
// this : window,
// arguments : [4,5],
// a : 4,
// b : 5,
// say : ,
// sum : undefined
// }
# 创建阶段
- 创建作用域链
- 通过变量对象VO创建活动AO
- 首先创建arguments对象
- 创建形参实参的键值对
- 创建函数声明
- 创建变量声明
# 执行阶段
- 变量赋值。函数引用,执行其他代码逻辑
- 当执行完毕后。执行上下文出栈,等待垃圾回收机制回收
# 函数申明提前
从AO对象的创建过程我们就可以发现,AO对象是先扫描函数体内的函数声明才去扫描变量声明。所以这也就是为啥会有声明提前。
# 变量提升
AO对象创建时已经将函数内部的变量提前扫描声明。是指在函数执行的过程中开始依次赋值。