ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

为什么在Javascript中声明之前可以访问变量?

2022-08-29 06:01:19  阅读:297  来源: 互联网

标签:执行 JavaScript 函数 代码 Javascript 访问 上下文 变量


为什么在Javascript中声明之前可以访问变量?

毫无疑问,当今最常用和最著名的语言之一是 JavaScript,如今它无处不在,我们可以创建 Web 应用程序和系统,在后端开发 API 并创建移动应用程序。

尽管它很受欢迎,但很多人不喜欢 JavaScript,主要是因为一些 特殊性 的语言与其他语言非常不同。

当我开始使用 JavaScript 时,让我感到困惑的一件事是 在声明之前使用变量或函数的可能性 而我相信很多人也觉得这有点奇怪。

在这篇文章中,我将尝试解释这是如何发生的。

Photo by 都铎·巴丘 on 不飞溅

执行上下文

在讨论变量和函数之前,我们需要了解一些关于 JavaScript 语言的概念,其中首先是上下文执行。

在 JavaScript 中,一个基本的执行单元是函数,我们一直使用它们来计算某些东西,执行副作用(如更改 UI),重用代码或使代码更易于理解。我们也知道一个函数可以调用另一个函数,而后者又可以调用另一个函数,以此类推……

当一个函数调用另一个函数时,代码执行必须回到调用它的位置,即:

当调用 对话 函数我们将调用另一个函数(在这种情况下 你好 ), 当。。。的时候 你好 函数执行完毕,我们需要回到调用它的地方,即在 对话 功能并继续执行。

但是,你有没有想过 JavaScript 引擎如何跟踪所有这些函数的运行并返回到代码中的特定位置?

在 JavaScript 中有两种主要类型的代码:全局代码和函数代码。

全球代码

这段代码是在所有函数之外定义的,即它们在我们的 JavaScript 中是松散的。

功能码

此代码在函数内部定义。

当我们的代码被 JavaScript 引擎执行时,每个语句都在特定的执行上下文中执行,并且由于我们有两种类型的代码,我们也有两种类型的上下文: 全局执行上下文函数执行上下文 .

它们之间最显着的区别是只有一个全局执行上下文,它是在 JavaScript 开始执行时创建的。 而对于每个函数调用,都会创建一个新的函数执行上下文。

因此,JavaScript 正是通过这些上下文来处理暂停、执行和回调。

我们知道 JavaScript 是基于 单线程执行模型 ,即一次只能执行一段代码。因此,每次调用函数时,都会暂停当前的执行上下文,并创建一个新的函数执行上下文,从中评估代码。在函数执行完它的任务后,也就是它的代码已经执行完毕,通常会丢弃该函数的执行上下文,并恢复之前的执行上下文。

所以有必要同时跟踪这两个上下文,也就是说,我们需要一个正在运行的执行上下文和另一个暂停的上下文。实现此功能的最简单方法是通过堆栈,称为 执行上下文堆栈 .

词汇环境

现在我们对执行上下文的工作原理有了更多了解,让我们来看看词法环境。

考虑以下示例:

在这种情况下,我们知道通过调用 控制台日志 函数会创建一个新的执行上下文,但是日志函数如何获取变量名的值呢?

这个过程称为 标识符解析 , 基本上的想法是 找出给定标识符引用的变量 ,执行上下文是通过词法环境来完成的。

词法环境是一种内部 JavaScript 机制 跟踪标识符到特定变量的映射 ,回到之前的代码:

访问变量名时会参考词法环境,即在 控制台日志 宣言。

词法环境是 JavaScript 作用域机制的内部实现,人们通常将它们称为作用域。

通常,词法环境与特定的代码结构相关联,它可以与函数、代码块或 catch(try/catch 的一部分)相关联,并且每个结构都可以有自己的标识符映射。

Javascript 中的变量类型

在 JavaScript 中,我们可以使用三个保留字来定义变量: 曾是 , 常量 .它们在两个方面有所不同:可变性以及它们与词汇环境的关系。

可变性

如果我们按照可变性方面对变量声明进行分类,我们可以把 常量 在一侧和 曾是 / 在另一。

所有变量定义为 常量 是不可变的,也就是说,它们的值只能设置一次。另一方面,所有变量定义为 曾是 或者 可以根据需要多次更改它们的值。

词汇环境

三种类型的变量定义( 曾是 , 常量 ) 也可以通过它们与词汇环境的关系(通过它们的范围)来分类,我们可以把 曾是 在一侧和 / 常量 在另一。

使用 var

当我们使用 曾是 定义类型,变量在最近的函数或全局词法环境中定义(块被忽略)。让我们看一下下面的例子:

JavaScript 的奇怪之处在于,让很多来自其他语言的人感到困惑的是,我们可以访问在这些块之外的块代码中定义的变量。

这是因为当我们用保留字声明变量时 曾是 他们是 在最近的函数或全局词法环境中注册 ,无论块范围如何。

使用 let 和 const

由于这种奇怪的行为,在 JavaScript 的 ES6 版本中,有两个新的变量声明类型 常量 已添加。

不像 曾是 , 他们在 最近的词汇环境 (它可以是块、循环、函数或全局)。

对前面的代码进行一些更改:

在此示例中,您无法访问 文本 for 循环之外的变量,您无法访问 信息 函数外的变量 你好 .因为,在这两种情况下,它都不在他们的词汇环境中。

在词法环境中注册标识符

JavaScript 语言的一个原则就是易于使用,所以我们不指定函数返回类型、参数类型、变量类型等等……而且你已经知道 JavaScript 代码是逐行执行的,那么让我们看看下面的例子:

如果代码是逐行执行的,我们如何调用 你好 声明之前的功能? JavaScript 代码的执行分两个阶段:

  1. 第一阶段在创建新的词法环境时激活,在此阶段不执行任何代码,但是 JavaScript 引擎会访问并注册在当前词法环境中声明的所有变量和函数。
  2. 在第二阶段,JavaScript 执行发生在第一阶段执行之后,此行为取决于变量声明类型(var、let 和 const)和环境类型(全局、函数或块)。

让我们看另一个例子:

在本例中,它将被记录 不明确的 在我们的控制台中,因为第一步将扫描并注册初始值未定义的每个变量的标识符。实际执行代码时,变量的值将设置为第二个。

这是因为变量类型 曾是 可以将它们的值未定义并在声明之前访问。

笔记: 如果变量是用 let 或 const 定义的,JavaScript 会抛出一个 ReferenceError 说我们不能在变量被声明之前访问它们。

结论

在这篇文章中,我们看到了为什么类型变量 曾是 可以在声明之前访问,以及如何在定义之前调用声明函数。

我们还看到了一些有趣的 JavaScript 概念,例如:执行上下文、词法环境、作用域、标识符解析和标识符。

谢谢阅读!在本平台关注我,阅读更多开发内容。祝你有美好的一天,很快再见!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/1358/49302905

标签:执行,JavaScript,函数,代码,Javascript,访问,上下文,变量
来源: https://www.cnblogs.com/amboke/p/16634656.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有