JavaScript Hoisting内部是如何工作的
简单来说,JavaScript中的hoisting指的是可以在变量声明之前使用变量。声明的变量在某种程度上被移动到作用域的顶部。然而,hoisting只适用于变量声明,而不适用于变量初始化。
虽然几乎任何有一点JavaScript经验的人都知道hoisting是什么,但很多人并不真正知道它发生的原因和其行为的原因。
JavaScript之所以以这种方式处理声明,原因在于JavaScript引擎执行代码的底层机制。因此,为了真正感受到Hoisting的发生,我们需要深入了解JavaScript代码执行的幕后情况。
JavaScript中的一切都发生在所谓的 执行上下文 中。执行上下文可以被视为在运行时跟踪代码评估的环境。
执行上下文有两个主要组成部分:
- 内存组件:以键值对的形式存储变量和函数。
- 代码组件:代码逐行执行。
为了看到Hoisting是如何在这个执行上下文中实际发生的,让我们来看一个示例。考虑以下简单的JavaScript代码:
Javascript
console.log(x);
x = 7;
console.log(x);
var x;
在这里,变量x在声明之前被使用(被打印和赋值)。如果我们应用变量提升的概念,我们可以轻松判断上面代码的输出结果为:
undefined
7
然而,让我们通过执行上下文来理解我们是如何得到这个输出的。
与上面的代码对应的全局执行上下文的创建将以以下方式进行:首先,内存分配阶段将发生,代码中存在的任何变量/函数将被扫描并分配内存。由于代码中没有函数,变量x将被分配内存空间,并分配了undefined占位符。经过此步骤后的全局执行上下文将如下所示:

现在,代码执行阶段将在代码组件内开始,在其中代码将从头开始逐行执行。所以,首先,变量 x 的值将会被打印到控制台上,因为在这个阶段变量 x 的存储值为 undefined。然后,在下一步中,值 7 将被赋给 x。完成这两个步骤后,更新后的执行上下文将类似于这样:

undefined
7
这正是预期的输出。因此,通过这个简单的示例,我们理解了提升实际上意味着什么,以及它是如何在内部实际发生的。
变量声明似乎移动到代码的顶部的原因现在可以通过执行上下文中的两个阶段的工作来解释。在执行任何代码之前,代码中出现的所有变量将被分配内存并分配值 undefined(即在任何其他代码之前,首先考虑的是声明)。只有在完成这一步骤后,使用该变量的代码才会在第二阶段中执行。这也解释了为什么变量初始化不会被提升。这是因为变量初始化基本上意味着“使用”变量,所以它只会在第二阶段中执行,即代码执行阶段。
极客教程