JavaScript 提升如何在内部工作?
简单来说,JavaScript 中的提升是指变量可以在声明之前使用。声明的变量以某种方式虚拟地移动到范围的顶部。但是,提升仅适用于变量声明,不适用于变量初始化。
虽然几乎任何对 JavaScript 有一点经验的人都知道什么是提升,但他们中的许多人并不真正知道它为什么会发生以及为什么它会以这种方式运行。
JavaScript 在声明方面表现出这种行为的原因在于 JavaScript 引擎如何执行代码的底层机制。因此,为了真正了解 Hoisting 是如何发生的,我们需要深入了解 JavaScript 代码执行的幕后情况。
JavaScript 中的一切都发生在所谓的执行上下文中。可以将执行上下文视为在运行时跟踪代码评估的环境。
执行上下文有两个主要组成部分:
- 内存组件:将变量和函数存储为键值对。
- 代码组件:代码一次执行一行。
要了解如何使用此执行上下文实际进行提升,让我们看一个示例。考虑以下简单的 JavaScript 代码:
Javascript
console.log(x);
x = 7;
console.log(x);
var x;
在这里,变量 x 在声明之前被使用(被打印并被赋值)。如果我们应用提升的概念,我们可以很容易地判断上述代码的输出为:
undefined
7
但是,让我们了解如何使用执行上下文获得此输出。
与上面显示的代码对应的全局执行上下文的创建将发生如下情况:首先,将发生内存分配阶段,其中将扫描代码中存在的任何变量/函数并分配内存。由于代码中没有函数,变量 x 将在内存中分配空间并分配未定义的占位符。此步骤之后的全局执行上下文将如下所示:
现在,代码执行阶段将在代码组件内部开始,代码将从头开始执行,一次一行。因此,首先,未定义的变量 x 的值将打印在控制台上,因为在此阶段为变量 x 存储的值是未定义的。然后在下一步中,将值 7 分配给 x。完成这两个步骤后,更新后的执行上下文将如下所示:
在下一行,我们再次打印 x 的值。由于现在 x 的值为 7(如上图所示),因此 7 将打印在控制台上。最后一行实际上是一开始就完成的声明行。
因此,我们上面编写的代码的最终输出将是:
undefined
7
这正是预期的输出。因此,在这个简单示例的帮助下,我们了解了提升的实际含义以及它实际上是如何在内部发生的。
变量声明似乎移到代码顶部的原因现在通过执行上下文中两个阶段的工作显而易见。在执行任何代码之前,代码中存在的所有变量都将被分配内存并分配值undefined (即在任何其他代码之前首先考虑声明)。只有在完成此操作后,使用该变量的代码才会在第二阶段执行。这也解释了为什么不提升变量初始化。这是因为变量初始化基本上意味着“使用”一个变量,因此它只会在代码执行的第二阶段执行。