javascript 执行上下文系列总结
我在文章《javascript 执行上下文》中介绍了 javascript 代码在执行时,会相应地创建对应执行上下文并将其入栈出栈的过程。
每个执行上下文会包含三个重要属性,分别是变量对象(Variable Object,VO)、作用域链(Scope Chain)和 this 指向。
而我在文章《javascript 变量对象》、《javascript 作用域链》和《javascript this 指向》中详细地描述了在代码执行过程中,随着执行上下文的创建和执行,这三个重要属性的变化过程,接下来我就一个例子结合前面四篇文章,详细地说明执行上下文的具体处理过程。
假设有一个 javascript 文件中包含如下代码
function fn1() { var a = 1; function fn2(b) { var c=3 } fn2(2) } fn1();
我们依旧可以很容易地知道,上述代码在执行过程中,执行上下文栈的变化过程如下
/*伪代码*/// 代码执行时最先进入全局环境,全局上下文被创建并入栈ECStack.push(globalContext);// fn1 被调用,fn1 函数上下文被创建并入栈ECStack.push(<fn1> functionContext);// fn1 中调用 fn2,fn2 函数上下文被创建并入栈ECStack.push(<fn2> functionContext);// fn2 执行完毕,fn2 函数上下文出栈ECStack.pop();// fn1 执行完毕,fn1 函数上下文出栈ECStack.pop();// 代码执行完毕,全局上下文出栈ECStack.pop();
我们已经知道,执行上下文在创建阶段,会分别生成变量对象、建立作用域链和确定 this 指向。那么我们接下来就按照上述代码的流程,详细说明各个执行上下文中这三个重要属性的情况。
首先进入全局环境,全局上下文被创建并入栈
全局上下文被创建时,其执行上下文如下
globalContext={ VO:globalObj Scope:[globalContext.VO] this:globalContext.VO }
接着 fn1 被调用,fn1 函数上下文被创建并入栈
这里需要说明的是,在 fn1 函数上下文被创建之前,会有一个函数定义(声明)过程,这个过程发生在全局上下文创建阶段,在这个过程中,fn1.[[scope]] 会保存其上层作用域的变量对象,所以此时 fn1.[[scope]]=[globalContext.VO]。
在 fn1 函数上下文创建阶段,其执行上下文如下
fn1Context={ VO:{ Arguments:{ length:0 }, fn2:<function fn2 reference>, a:undefined }, Scope:[fn1Context.VO,globalContext.VO] this:globalContext.VO }
在 fn1 函数上下文执行阶段,其执行上下文如下
fn1Context={ VO:{ Arguments:{ length:0 }, fn2:<function fn2 reference>, a:1 }, Scope:[fn1Context.VO,globalContext.VO] this:globalContext.VO }
然后在 fn1 中调用 fn2,fn2 函数上下文被创建并入栈
同理可知,在 fn1 函数上下文创建阶段,fn2.[[scope]]=[fn1Context.VO,globalContext.VO]。
所以在 fn2 函数上下文创建阶段,其执行上下文如下
fn2Context={ VO:{ Arguments:{ 0:2, length:0 }, b:2 c:undefined }, Scope:[fn2Context.VO,fn1Context.VO,globalContext.VO] this:globalContext.VO }
在 fn2 函数上下文执行阶段,其执行上下文如下
fn2Context={ VO:{ Arguments:{ 0:2, length:0 }, b:2 c:3 }, Scope:[fn2Context.VO,fn1Context.VO,globalContext.VO] this:globalContext.VO }
最后是各个上下文出栈
在各个上下文出栈后,其对应的变量对象会被 javascript 中的自动垃圾收集机制回收。
而我们经常说闭包能够访问其所在环境的变量,其实是因为闭包能够阻止上述变量对象被回收的过程。
关于 javascript 执行上下文系列,暂时就写这么多,以后有更深入的感悟,会继续补充的吶。
但其实我还漏了一个很重要的知识点,就是上面说的闭包啦,闭包跟变量对象以及作用域链有着千丝万缕的关系,后续我将用单独一篇文章介绍闭包,嗯哼。
作者:淘淘笙悦
链接:https://www.jianshu.com/p/1e5c85cebcc0
共同学习,写下你的评论
评论加载中...
作者其他优质文章