javascript中的执行上下文堆栈和执行上下文

原文链接:http://weizhifeng.net/javascript-the-core.html

执行上下文堆栈

这里有三种类型的ECMAScript代码:全局代码、函数代码和eval代码。每个代码是在其执行上下文(execution context)中被求值的。这里只有一个全局上下文,可能有多个函数执行上下文以及eval执行上下文。对一个函数的每次调用,会进入到函数执行上下文中,并对函数代码类型进行求值。每次对eval函数进行调用,会进入eval执行上下文并对其代码进行求值。


注意,一个函数可能会创建无数的上下文,因为对函数的每次调用(即使这个函数递归的调用自己)都会生成一个具有新状态的上下文:

function foo(bar) {}

// call the same function,
// generate three different
// contexts in each call, with
// different context state (e.g. value
// of the "bar" argument)

foo(10);
foo(20);
foo(30);

一个执行上下文可能会触发另一个上下文,比如,一个函数调用另一个函数(或者在全局上下文中调用一个全局函数),等等。从逻辑上来说,这是以栈的形式实现的,它叫作执行上下文栈。

一个触发其他上下文的上下文叫作caller。被触发的上下文叫作callee。callee在同一时间可能是一些其他callee的caller(比如,一个在全局上下文中被调用的函数,之后调用了一些内部函数)。

当一个caller触发(调用)了一个callee,这个caller会暂缓自身的执行,然后把控制权传递给callee。这个callee被push到栈中,并成为一个运行中(活动的)执行上下文。在callee的上下文结束后,它会把控制权返回给caller,然后caller的上下文继续执行(它可能触发其他上下文)直到它结束,以此类推。callee可能简单的返回或者由于异常而退出。一个抛出的但是没有被捕获的异常可能退出(从栈中pop)一个或者多个上下文。

换句话说,所有ECMAScript程序的运行时可以用执行上下文(EC)栈来表示,栈顶是当前活跃(active)上下文:



当程序开始的时候它会进入全局执行上下文,此上下文位于栈底并且是栈中的第一个元素。然后全局代码进行一些初始化,创建需要的对象和函数。在全局上下文的执行过程中,它的代码可能触发其他(已经创建完成的)函数,这些函数将会进入它们自己的执行上下文,向栈中push新的元素,以此类推。当初始化完成之后,运行时系统(runtime system)就会等待一些事件(比如,用户鼠标点击),这些事件将会触发一些函数,从而进入新的执行上下文中。

在下个图中,拥有一些函数上下文EC1和全局上下文Global EC,当EC1进入和退出全局上下文的时候下面的栈将会发生变化:


这就是ECMAScript的运行时系统如何真正地管理代码执行的。

更多有关ECMAScript中执行上下文的信息可以在对应的第一章 执行上下文中获取。

像我们所说的,栈中的每个执行上下文都可以用一个对象来表示。让我们来看看它的结构以及一个上下文到底需要什么状态(什么属性)来执行它的代码。


执行上下文

一个执行上下文可以抽象的表示为一个简单的对象。每一个执行上下文拥有一些属性(可以叫作上下文状态)用来跟踪和它相关的代码的执行过程。在下图中展示了一个上下文的结构:


除了这三个必需的属性(一个变量对象(variable objec),一个this值以及一个作用域链(scope chain))之外,执行上下文可以拥有任何附加的状态,这取决于实现。

让我们详细看看上下文中的这些重要的属性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值