执行上下文
一、当JS在运行代码的时候,会产生三种执行上下文:
1、全局执行上下文
2、函数执行上下文
3、eval执行上下文
每个执行的上下文都有三个重要的属性:
1、变量对象(VO):包含变量,函数声明,函数形参,该属性只能在全局上下文中访问
2、作用域链:(JS采用词法作用域,也就是说变量在定义的时候就决定了)
3、this指针
对于以下代码:
var a = 10 function foo(i) { var b = 20 } foo()
在执行栈中,有两个执行上下文:函数执行上下文和全局执行上下文;
对于全局执行上下文:VO是这样的
globalContext.VO === globe
globalContext.VO = {
a: undefined,
foo: <Function>,
}
对于函数执行上下文:
fooContext.VO === foo.AO
fooContext.AO {
i: undefined,
b: undefined,
arguments: <>
}
//arguments是函数独有的对象,箭头函数没有,该对象是一个伪数组,有length且可以通过下标访问元素。该对象的callee属性代表函数本身,caller代表函数的调用者。
作用域链scope:可以看成是包含自身变量对象和父级变量对象的列表,可以通过属性[[Scope]]查找父级变量对象。
所以在变量提升出现undefine的解释为:在生成执行上下文的时候,分为两个阶段,创建阶段生成变量对象VO,并在栈中开辟空间,给变量赋值undefined,所以代码执行阶段,可以直接调用。
而let声明的变量不能提前使用因为,let申明了变量,但并未对其进行赋值,所以临时性死区导致其不能被提前调用。
!注:对于非匿名立即执行函数,js解释器会生成一个辅助的特定对象,然后将名称作为这个对象的属性,因此函数内部才可以访问到外部变量,但是访问的值是只读的,不能对其进行赋值.
二、代码执行过程
1、创建全局执行上下文,从上到下执行全局上下文。
2、遇到函数,函数的执行上下文(callee)被push到执行栈的顶层
3、函数执行上下文被激活,开始执行函数,caller被挂起
4、函数执行完成,callee被移除执行栈 ,控制权交换全局上下文(caller),继续执行。

浙公网安备 33010602011771号