首页 > 编程语言 >为什么在Javascript中声明之前可以访问变量?

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

时间:2022-08-29 05:55:22浏览次数:90  
标签:执行 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,访问,上下文,变量
From: https://www.cnblogs.com/amboke/p/16634656.html

相关文章

  • JavaScript--关于this
    一、为什么会有this的出现  “this关键词是JS中最复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数的作用域中”根据凯尔辛普森的书中描述,刚开始阅读时我对......
  • leetcode 斐波那契数列 javascript实现
    写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项(即F(N))。斐波那契数列的定义如下:F(0)=0,  F(1) =1F(N)=F(N-1)+F(N-2),其中N>1.斐波那契数列由0......
  • JavaScript的函数
    //alert是JavaScript语言提供的一个警告函数//它可以接收任意类型的参数,这个参数就是警告框的提示信息   <!DOCTYPEhtml><htmllang="en"><head><metacharse......
  • rh358 002 fact变量获取 ansible配置网络 service_facts
    通过ansible获取网络信息1.如何获取fact事实变量方式1:ansibleservera-mservera方式2:剧本[root@workstationansible]#catake.yaml----name:getallfac......
  • JavaScript基础介绍三(事件)
    原生js事件绑定我们直接写几个案例,看懂即可开关灯案例变色<script>letbtnEle=document.getElementById('d2')letdivEle=document.getElementById('......
  • RBAC访问控制
    案例:为指定用户授权访问不同命名空间权限,例如公司新入职一个小弟,希望让他先熟悉K8s集群,为了安全性,先不能给他太大权限,因此先给他授权访问default命名空间od,读取权限。实......
  • GitHub访问速度过慢的解决办法
    1、打开网站:https://www.ipaddress.com/2、查询IP:查询github.com,记录IP:140.82.113.4查询github.global.ssl.fastly.net,记录IP: 151.101.1.1943、修改dns缓存打开本地文......
  • 初识JavaScript
    目录JS的组成JS有三种书写位置:行内、内嵌、外部1.行内式JS2.内嵌式JS3.外部式JSJS注释JS输入输出语句变量1.声明变量2.赋值3.变量的初始化4.变量扩展5.变量命名规范数据......
  • 初识JavaScript
    目录JS的组成JS有三种书写位置:行内、内嵌、外部1.行内式JS2.内嵌式JS3.外部式JSJS注释JS输入输出语句变量1.声明变量2.赋值3.变量的初始化4.变量扩展5.变量命名规范数据......
  • 让你的PLC支持多连接,多电脑同时访问一个PLC 连接PLC的权限设置,PLC同时多连接
    要明白一个技术,首先要明白它到底是解决什么问题的?你是不是有以下的困扰1.我有个三菱的PLC,只能配置一个端口,但是有多台电脑需要从PLC进行读写,因为三菱是单链接的,所以直接读......