JavaScript执行上下文之调用栈和多执行上下文(二)

26 篇文章 1 订阅

在上一篇文章中我们讨论了有关执行上下文,它是编译阶段创建的第一个执行上下文。

我们称这个第一个执行上下文为全局执行上下文(global EC),这个执行上下文存储的相关变量是全局变量。

全局执行上下文并不是唯一的,当脚本运行时,多个执行上下文可以被创建或移出。

那么这些执行上下文来自哪?

一个执行上下文与编译阶段联系在一起,那么多个执行上下文暗示有多个编译阶段。

这个机制与函数有关

上面的代码中,我们知道在程序运行结束后控制台会打印20,但是在执行上下文里到底发生了什么?

一如既往,从编译开始,首先创建一个全局执行上下文

在变量环境中,我们可以看见“apple”,“appleTotal”变量和“total”函数,编译结束,并且执行开始。

“apple”变量的值被更新为10,然后js引擎阅读“total()”部分

在此刻,同样两个步骤被重复。编译阶段开始,但是这个时候,它仅仅发生在total函数

js引擎创建一个新的执行上下文,total函数的执行上下文,并且将它堆叠在全局执行上下文的顶部,我们称这个结构为栈。

栈有一个特点:后进,先出。这也是我们在这个机制中唯一关心的特点。

与全局执行上下文相同,一个变量环境存在与total函数执行上下文中,里面一个值为undefined的“price”变量

接下来,total函数的执行上下文开始执行阶段,“price”变量的值被更新为2

然后,这个函数在total执行上下文找到“price”变量,在全局执行上下文找到“apple”变量。

很好,它找到了所有变量并计算出结果返回

在同一时刻,这个返回值在全局执行上下文中被赋值给“appleTotal”变量。

接下来total执行上下文中没有可执行的脚本了,所以js引擎将它从栈中移出。

total执行上下文是最后一个进栈的,所以它是第一个离开栈的。

现在,栈底还有最后一个执行上下文,全局执行上下文。

仅仅保留的可执行脚本是在控制台打印appleTotal的值,这个做完后,整个程序运行完成。

从这个例子中,我们可以看到js引擎如何管理执行栈。

  • js引擎在一个函数被调用之前不会编译这个函数里的代码
  • 当一个函数被编译,一个新的执行上下文被创建,并且被放置到栈顶
  • 所有的执行上下文被管理在一个栈结构中,这个过程发生从栈顶到栈底
  • 任何时候一个函数被调用,都会发生编译和执行两个步骤

根据执行上下文在栈顶相互堆叠,我们称之为调用栈。

在浏览器中检擦你的js调用栈

当代浏览器,在它的开发工具中很容易检查它的调用栈

以chrome为例

为了检查调用栈,我们需要:

  • 一个HTML文件
  • 一个断点

HTML文件的代码如下,当然,你也可以给出自己的代码

<script>
var apple = 10;
function total() {
 var price = 2;
 return apple * price;
}
var appleTotal = total();
console.log(appleTotal);
</script>

在chrome中运行这个HTMl文件,并且在开发者工具中打开source面板

在source面板上,我们在total函数里打一个断点

接下来刷新页面,调用栈将会展示出来。那个total是total函数的执行上下文,并且“anonymous”是全局执行上下文。

结论:

  • 多个执行上下文是被管理在一个栈结构中,被称为js调用栈。
  • js引擎重复两个步骤过程,编译和执行,为了添加和移除执行上下文。
  • 新的执行上下文被添加到栈的最上面,最上面的执行上下文优先完成执行。
  • 仅仅只有一个全局执行上下文,并且它总是在栈的底部,它在浏览器开发工具中展示为“anonymous”(匿名)调用栈。

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值