理解提升

2025-06-07

理解提升

介绍

在讨论代码提升之前,我认为有必要先了解一下 JavaScript 引擎是如何查看、解释和运行代码的。一旦我们理解了这一点,代码提升就变得很容易解释了。

执行上下文

JavaScript 引擎将代码分解成更小的片段,以降低解释和运行的复杂性。为了更容易地解释这一点,想象一下你尝试编写 Web 应用程序的场景。你的应用程序通常由模块、函数、变量声明等组成。本质上,你已将应用程序分解成逻辑部分,以便于理解、维护和调试它。

就像模块、函数等机制可以让你管理程序的复杂性一样,执行上下文是 JavaScript 引擎管理代码解释复杂性的方式。希望以上解释能让事情更清晰一些。

全局执行上下文

JavaScript 引擎运行代码时创建的第一个执行上下文称为“全局执行上下文”。最初,这个执行上下文由两部分组成——一个全局对象和一个名为“this”的变量。

执行上下文

上图展示了全局执行的最基本形式。 this 关键字引用的是全局对象,即 window 对象。

创建和执行阶段

现在我们了解了全局执行上下文,让我们了解运行任何 JavaScript 程序时存在的两个阶段。

让我们考虑以下代码示例:

var fruit = apple;

function getFruit() {
    return fruit;
}
Enter fullscreen mode Exit fullscreen mode

创建阶段

下图描述了全局执行上下文在创建阶段的样子。

创建阶段

在全局 Creation 阶段,JavaScript 引擎将:

  1. 创建一个全局对象。
  2. 创建一个名为“this”的对象。
  3. 为变量和函数设置内存空间。
  4. 将任何函数声明放入内存中时,为变量声明分配默认值“undefined”。

执行阶段

下图描述了全局执行上下文在执行阶段的样子。

执行阶段

在全局Execution阶段,JavaScript 引擎将:

  1. 开始逐行运行代码。
  2. 将“真实”值分配给内存中已经存在的变量。

现在我们已经了解了创建和执行阶段,让我们再举一个例子,看看控制台上的输出。

console.log(`The fruit is ${fruit}`);
console.log(`The color is ${color}`);

var fruit = 'apple';
var color = 'red';

function getFruit() {
    return fruit;
}

function getColor() {
    return color;
}

//Output
//The fruit is undefined
//The color is undefined
Enter fullscreen mode Exit fullscreen mode

注意事项:

  • 在创建阶段,变量“fruit”和“color”被初始化为值“undefined”。
  • 因此,当遇到 console.log 语句时,控制台上会打印值“undefined”。

提升

在创建阶段为变量声明分配默认值“undefined”的过程称为提升。

关于“提升”的令人困惑之处在于,实际上并没有任何东西被“提升”或移动。很多其他的解释都只讨论了代码变量和函数在执行前是如何在栈上向上移动的,而没有明确说明执行上下文中的创建和执行阶段。

理解了提升之后,下面的代码的简单示例就会变得有意义。

//The Variable x is initialized
x = 5;

//Output the value of x multiplied by 2 on the console
console.log(x * 2);

//The variable x is declared over here
var x;

//Output -> 10
Enter fullscreen mode Exit fullscreen mode

在上面的代码示例中,你会注意到变量“x”在第一个语句中被初始化,然后在最后一个语句中声明了x。但是,当JavaScript引擎处于创建阶段时,它会将声明语句向上移动到堆栈的顶部,因此当JavaScript引擎运行上述程序时,它看起来如下所示。

//The variable x is declared over here
var x;

//The Variable x is initialized
x = 5;

//Output the value of x multiplied by 2 on the console
console.log(x * 2);

//Output -> 10
Enter fullscreen mode Exit fullscreen mode

理想情况下,我本以为 JavaScript 引擎会因为使用未声明的变量而抛出错误,但多亏了 ES6,这个问题已经通过 let & const 解决了。您可以点击此处了解更多关于 let & const 的信息。

什么没有被提升?

我们说使用 let 和 const 的变量声明不会被提升。此外,以下声明也不会被 JavaScript 引擎提升:

  • 用表达式定义的函数。
  • 箭头函数。

结论

提升只不过是在创建阶段为变量声明分配默认值“未定义”的过程。

我建议你现在就直接跳到我关于闭包的文章,因为它是本文中描述的概念的延续。你可以在这里阅读。

希望你喜欢这篇文章。请告诉我你的反馈,但不要分享给你的朋友。

您可能还感兴趣:

文章来源:https://dev.to/skaytech/understanding-hoisting-b48
PREV
CSS 中的水平和垂直居中
NEXT
ES6 高阶函数