https://segmentfault.com/a/1190000012646488 https://yangbo5207.github.io/wutongluo/
说明:此处只是记录阅读前端基础进阶的理解和总结,如有需要请阅读上面的链接
一、执行上下文的生命周期
1.创建阶段:在创建阶段会创建变量对象,确定作用域链,以及this指向
2.执行阶段:执行其他代码,包括给变量赋值和执行其他代码
二、创建阶段的具体过程:
1.建立arguments对象。即给函数参数建立对应的变量对象,并存储参数值
2.检查当前上下文的函数声明(即用function声明的函数)用函数名建立一个变量对象,对象的值是指向函数的地址指针,如果同名的变量对象已存在则覆盖原变量对象的值
3.检查当前上下文的变量声明(以var声明的)给变量名建立对应的变量对象并赋值undefined,如果同名的变量对象已存在则不建立,原变量对象的值不受影响
console.log(foo); // function foo
var foo = 20;
function foo() { console.log('function foo') }
上面的例子,根据执行上下文的生命周期,JavaScript引擎会先创建函数foo的变量对象VO{foo},值为函数foo的地址指针,然后再检查变量声明要建立变量foo的变量对象时发现同名的变量对象foo已存在所以跳过建立,创建阶段完成,接着进入执行阶段。首先打印到控制台console.log(foo),然后给变量对象foo赋值20
因此正确的执行顺序是:
// 首先将所有函数声明放入变量对象中
function foo() { console.log('function foo') }
// 其次将所有变量声明放入变量对象中,但是因为foo已经存在同名函数,因此此时会跳过undefined的赋值
// var foo = undefined;
// 然后开始执行阶段代码的执行
console.log(foo); // function foo
foo = 20;
从实际执行的顺序看,函数foo的位置提升到了第一行,这就是大家常说的变量提升的问题。
执行上下文未进入执行阶段时变量对象是不能访问的,进入执行阶段后变量对象转换为活动对象(AO)变量对象就能访问了。因此变量对象和活动对象他们其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象