执行上下文的生命周期:
创建阶段:创建变量对象,建立作用域链,以及确定this的指向。
代码执行阶段:变量赋值,函数引用,以及执行其他代码。
变量对象的创建过程:
建立arguments对象。检查当前上下文中的参数,建立该对象下的属性与属性值。
检查当前上下文的函数声明,也就是使用function关键字声明的函数。以函数名建立属性,属性值为指向该函数所在内存地址的引用。如果函数名的属性已经存在,那么该属性将会被新的引用所覆盖。
检查当前上下文中的变量声明,每找到一个变量声明,就在变量对象中以变量名建立一个属性,属性值为undefined。如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。
testEC = {
// 变量对象
VO: {},
scopeChain: {}
}
// VO 为 Variable Object的缩写,即变量对象
VO = {
arguments: {...}, //注:在浏览器的展示中,函数的参数可能并不是放在arguments对象中,这里为了方便理解,我做了这样的处理
foo: <foo reference> // 表示foo的地址引用
a: undefined
}
变量对象和活动对象有什么区别,他们其实都是同一个对象,只是处于执行上下文的不同生命周期。不过只有处于函数调用栈栈顶的执行上下文中的变量对象,才会变成活动对象。
// demo2
function test() {
console.log(foo);
console.log(bar);
var foo = 'Hello';
console.log(foo);
var bar = function () {
return 'world';
}
function foo() {
return 'hello';
}
}
test();
// 创建阶段
VO = {
arguments: {...},
foo: <foo reference>,
bar: undefined
}
// 这里有一个需要注意的地方,因为var声明的变量当遇到同名的属性时,会跳过而不会覆盖
// 执行阶段
VO -> AO
VO = {
arguments: {...},
foo: 'Hello',
bar: <bar reference>,
this: Window
}
全局上下文有一个特殊的地方,它的变量对象,就是window对象
作者:这波能反杀
链接:https://www.jianshu.com/p/330b1505e41d
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
原文:https://www.cnblogs.com/bingery/p/11331403.html