欢迎光临
我们一直在努力

什么是Javascript调用上下文(Execution Context)? 什么是javascript调用堆栈?

Javascript中什么是调用上下文

我猜你不知道这个答案。

编程语言最基本的组成部分是什么?

变量和函数对吗?每个人都可以学习这些模块。

但是什么是基础呢?

在成为中级(甚至高级)JavaScript开发人员之前,您应该掌握哪些JavaScript的知识?有很多:作用域、闭包、回调、原型等等。

但是在深入了解这些概念之前,你至少应该理解JavaScript引擎是如何工作的

在这篇文章中,我们将遍历每个JavaScript引擎的两个基本部分:执行上下文和调用堆栈。(不要害怕。这比你想象的容易)

你将学到什么

  • JavaScript引擎是如何工作的
  • JavaScript中的执行上下文
  • 调用堆栈是什么
  • 全局执行上下文与本地执行上下文的区别

JavaScript如何运行代码?

JavaScript如何运行代码?

如果你是高级开发人员,你可能已经知道答案了。

如果你是初学者,我们将共同努力。

事实上,JavaScript内部结构并不容易。

但我保证你能学会它们。

当你学会它们的时候,你会觉得自己更有力量,更聪明。

通过查看JavaScript内部功能,您将成为一个更好的JavaScript开发人员,即使您不能掌握每一个细节。

现在,看看下面的代码:

var num = 2;
function pow(num) {
     return num * num;
}

看起来不难!

现在告诉我:你认为浏览器会评估那个代码的顺序是什么?

换句话说,如果你是浏览器,你将如何阅读该代码?

听起来很简单。

大多数人认为“是的,浏览器执行函数POW并返回结果,然后它分配2到NUM。”

你想知道我学生的答案吗?

从上到下

浏览器将从函数POW开始,计算num * num

JS引擎将逐行运行代码(种类)

我一直期待着。

我说过几年前同样的事情。

在下一节中,你会发现那些看似简单的代码行背后的机制。

JavaScript引擎

你只想成为一个普通的JavaScript开发者吗?

我敢打赌你不会的。

如果你想在JavaScript面试中留下好印象,你至少应该知道JavaScript是如何运行你的代码的。

(还有一些其他的东西,我不会在这里涉及)。

不要急于这些概念。

一天之内你什么也学不到。这需要时间。

好消息?我要让每个人都明白这一点(至少我会尝试)。

要理解JavaScript如何运行代码,我们应该遇到第一件可怕的事情:

执行上下文。

JavaScript中的执行上下文是什么?

每次在浏览器(或节点)中运行JavaScript时,引擎都会经历一系列的步骤。

其中一个步骤涉及创建全局执行上下文。

等一下瓦伦蒂诺,引擎是什么?

也就是说,JavaScript引擎是运行JavaScript代码的“引擎”。

现在有两个著名的JavaScript引擎:Google V8SpiderMonkey(蜘蛛猴)

V8是谷歌的开源JavaScript引擎,用于谷歌浏览器和NoDE.js。

SpiderMonkey是Mozilla的JavaScript引擎,用于Firefox。

到目前为止,我们有JavaScript引擎和执行上下文。

现在是时候了解他们是如何合作的。

它是如何工作的?

每次运行一些JavaScript代码时,引擎都会创建一个全局执行上下文。

执行上下文是用来描述JavaScript代码运行的环境的一个花哨词。我感觉到你很难想象这些抽象的东西。现在将全局执行上下文视为一个框:

Javascript: What Is The Execution Context?

来看一下我们的代码

var num = 2;
function pow(num) {
    return num * num;
}

引擎是如何读取代码的?

这里有一个简化的版本:

引擎:一号线。有个变量!酷。让我们把它存储在全局内存中。

引擎:三号线。我看到一个函数声明。酷。让我们把它存储在全局内存中!

引擎:看来我完了。

如果我再问你一次:浏览器怎么看下面的代码,你会怎么说?

是的,从上到下,但是…

正如你所看到的引擎没有运行函数POW!

它是函数声明,而不是函数调用。

上面的代码将在全局内存中存储的一些值中转换:函数声明和变量。

全局存储器?

瓦伦蒂诺,我已经被执行上下文弄糊涂了,现在你把全局内存扔给我了?

是的,我是。

让我们看看全局内存是什么。

全局存储器

JavaScript引擎也有一个全局内存。

全局内存包含全局变量和函数声明供以后使用。

如果您阅读Kyle Simpson的“作用域和闭包”,您可能会发现全局内存与全局作用域的概念重叠。

事实上,它们是一样的东西。

我飞了10000英尺高,这是有原因的。

这些都是很难理解的概念。

但现在你不必担心。

我想让你们理解我们的两个重要问题。

当JavaScript引擎运行您的代码时,它创建:

  • 全局执行上下文
  • 全局内存(也称为全局作用域或全局变量环境)

一切都清楚了吗?

如果我是你的话,我会:

写一些JavaScript代码
逐个解析代码,因为您是引擎
在执行期间对全局执行上下文和全局内存进行图形化表示。
你可以把练习写在纸上或者用一个原型工具。

对于我的小例子,图片看起来是这样的:

A graphic representation of Javascript Execution Context / Global Memory

在下一节中,我们将看到另一个可怕的事情:调用堆栈。

调用堆栈是什么?

你清楚执行上下文、全局内存和JavaScript引擎是如何结合在一起的吗?

如果不花时间复习前一节。

我们将在我们的谜题中引入另一个部分:调用堆栈。

让我们先回顾一下JavaScript引擎运行代码时会发生什么。

它创造:

  • 全局执行上下文
  • 全局存储器

除此之外,在我们的例子中没有发生任何事情:

var num = 2;

function pow(num) {
    return num * num;
}

代码是纯值的分配。

让我们再向前走一步。如果调用函数,会发生什么?

var num = 2;

function pow(num) {
    return num * num;
}

var res = pow(num);

有趣的问题。

在JavaScript中调用函数的行为使引擎请求帮助。

这个帮助来自JavaScript引擎的一个朋友:调用堆栈。

这听起来可能不是很明显,但是JavaScript引擎需要跟踪正在发生的事情。

它依赖于调用堆栈。

JavaScript中的调用堆栈是什么?

调用堆栈就像程序当前执行的日志。

实际上,它是一个数据结构:一个堆栈。

调用堆栈究竟是如何工作的?

毫不奇怪,它有两种方法:PUP和POP。

推动是将某物放入堆栈中的行为。

也就是说,当您在JavaScript中运行函数时,引擎将该函数推送到调用堆栈中。

每个函数调用都被推送到调用堆栈中。

第一个被推的东西是main()(或GULL()),JavaScript程序的主要线程。

现在,前面的图片看起来是这样的:

Javascript Call Stack

在另一端输出的是从堆栈中移除某物的行为。

当函数结束时,函数从调用堆栈中输出。

我们的调用堆栈看起来如下:

Javascript Call Stack pop

现在呢?你已经准备好从那里掌握每一个JavaScript概念了。

我不是开玩笑的。

但哪里没有完成!转到下一节!

本地执行上下文

到目前为止一切似乎都很清楚。

我们错过什么了吗?

我们知道JavaScript引擎创建全局执行上下文和全局内存。

然后,当您在代码中调用函数时:

  • JavaScript引擎请求帮助
  • 这个帮助来自JavaScript引擎的一个朋友:调用堆栈
  • 调用堆栈跟踪代码中调用什么函数的轨迹。

当你在JavaScript中运行函数时,还有另外一件事要发生。

首先,函数出现在全局执行上下文中。

然后,另一个迷你上下文出现在函数旁边:

这个新的小框被称为本地执行上下文。

什么??

如果您注意到,在前面的图片中,全局内存中出现了一个新变量:var RES.

变量RES首先具有未定义的值。

然后,当POW出现在全局执行上下文中时,函数执行并且RES获取其返回值。

在执行阶段,创建本地执行上下文以保存局部变量。

多么强大的概念。

During the execution phase a Local Execution Context gets created, alongside a Local Memory for holding up local variables.

记住这一点:

了解全局和本地执行上下文是掌握作用域和闭包的关键。

总结

你能相信4行代码后面是什么吗?

JavaScript引擎创建执行上下文、全局内存和调用堆栈。

但是,一旦调用函数,引擎就创建具有本地内存的本地执行上下文。

在这篇文章的末尾,你应该能够理解当你运行一些JavaScript代码时会发生什么。

经常被忽略的是,JavaScript内部构件总是被新开发人员视为是错误的东西。

然而,它们是掌握先进JavaScript概念的关键。

如果您学习执行上下文、全局内存和调用堆栈,那么作用域、闭包、回调和其他内容将是轻而易举的。

特别是,理解调用堆栈是最重要的。

一旦你可视化它,所有的JavaScript将开始变得有意义:你最终会理解为什么JavaScript是异步的,以及为什么我们需要回调。

你知道4行JavaScript代码后面是什么吗?

现在你知道了。

谢谢阅读!

赞(1)
版权归原作者所有,如有侵权请告知。达维营-前端网 » 什么是Javascript调用上下文(Execution Context)? 什么是javascript调用堆栈?

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址