深入--执行上下文

在《深入--词法作用域与动态作用域》中,提出这样一道思考题

var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
    var scope = "local scope";
    function f(){
        return scope;
    }
    return f;
}
checkscope()();

 两段代码都会打印‘local scope’,虽然两段代码执行的结果一样,但是两段代码究竟有哪些不同呢?

紧接着就在《深入--执行上下文栈》中,讲到了两者的区别在于执行上下文栈的变化不一样,然而回答的太笼统,本片详细解析执行上下文栈和执行上下文具体变化过程

具体执行分析

第一段代码执行过程:

1.执行全局代码,创建全局执行上下文,全局执行上下文被压入执行上下文栈

ECStack = [
     globalContext
];

 2.全局上下文初始化

globalContext = {
    VO:[global,scope,checkscope],
    Scope:[globleContext.VO],
     this:globleContext.VO
}

 3.全局上下文初始化的同时,checkscope函数被创建,保存作用域链到函数的内部属性[[scope]]

checkscope.[[scope]] = [
  globalContext.VO
];

 4.执行checkscope函数,创建checkscope函数执行上下文,并压入栈

ECStack = [
   checkscopeContext,
   globalContext
];

 5.checkscope函数执行上下文初始化:

①复制函数[[scope]]属性创建作用域链

②用arguments创建活动对象

③初始化活动对象,即加入形参、函数声明、变量声明

④将活动对象压入checkscope作用域链顶端

同时f函数被创建,保存checkscope作用域链到f函数内部属性[[scope]]

checkscopeContext = {
     AO:{
            arguments:{
                   length:0
            },
            scope:undefined,
            f:reference to function f(){}
     },
     Scope:[AO,globalContext.VO],
     this:undefined
}

6.执行f函数,创建f函数执行上下文并压入栈

ECStack = [
      fContext,
      checkscopeContext,
      globalContext
];

 7.f函数执行上下文初始化,跟上面一样:

①复制函数[[scope]]属性创建作用域链

②用arguments创建活动对象

③初始化活动对象,即加入形参、函数声明、变量声明

④将活动对象压入f作用域链顶端

fContext = {
     AO:{
            arguments:{
                     length:0
            }
     },
      Scope:[AO,checkscopeContext.AO,globalContext.VO],
      this.undefined
}

 8.f函数执行,沿这作用域链查找scope值并返回

9.f函数执行完毕,f函数上下文从执行上下文栈中弹出

ECStack = [
   checkscopeContext,
    globalContext
];

 10.checkscope函数执行完毕,checkscope执行上下文从执行上下文栈中弹出

ECStack = [
    globalContext
];

第二段代码就留给大家去尝试模拟它的执行过程

在下一篇《深入--闭包》中也会提及这段代码的执行过程

猜你喜欢

转载自xiaoxiaoher.iteye.com/blog/2377826
今日推荐