JavaScript 提升

2025-05-25

JavaScript 提升

提升是每个 JavaScript 及其相关框架开发人员都应该熟悉的重要概念之一。您是否想过,在声明函数调用或变量访问之前,如何进行这些操作?如果答案是肯定的,那么欢迎来到JavaScript 提升的世界

什么是提升?

这是前端开发中最常见的面试问题之一,常见的答案是“
所有变量和函数声明都移到顶部”。 真的吗?😮代码提升并非你所想的那样!!!😕 今天的文章中,我们将讨论并澄清有关代码提升的所有内容。
提升


误解

如果你正在搜索并学习提升,几乎所有地方你都会看到相同的定义。这也许对初学者来说很友好,但绝对不是这样。在 JavaScript 中,不会有任何内容被移动 让我们详细讨论一下。
JavaScript 提升

在开始之前,让我们先了解一下我们的代码是如何在 JavaScript 引擎中执行的。JavaScript
引擎会运行我们的代码两次。第一次(创建阶段)——引擎会遍历代码,并为变量和函数的声明分配内存。第二次(执行阶段)是引擎真正执行代码,逐行执行,进行赋值、调用函数等等。

变量提升

变量是任何编程语言的基本组成部分之一,每种语言对变量声明和交互方式的定义,决定了该编程语言的成败。因此,任何开发人员都需要了解如何有效地使用变量及其属性。

console.log('myName',myName);
var myName = 'JavaScript';
console.log('myName',myName);
Enter fullscreen mode Exit fullscreen mode

如果你看一下上面的例子,当你尝试运行代码时,它不会抛出错误。第一个会是undefined,第二个会是Javascript

这是因为无论如何声明变量,JavaScript 总会经历这些生命周期来声明变量,

  1. 宣言
  2. 初始化
  3. 利用率。

因此,
根据这个生命周期,上面的示例代码将被拆分为

var myName -> Declaration
myName = 'JavaScript' -> Initialization
console.log('myName',myName); -> Utilization.
Enter fullscreen mode Exit fullscreen mode

因此,在第一次运行中,JavaScript 会检查变量/函数的声明并分配内存空间。此时,所有变量都会被声明一个默认值,undefined而在第二次运行所有代码时,JavaScript 会为所有变量分配实际值。

实际定义:
JavaScript 实际上会在执行代码之前扫描代码,获取所有变量并分配单独的内存空间。只是变量声明会先执行,因此它们会位于保留内存中
。MDN

ES6推出后,JavaScript中的变量可以通过三种类型声明:var、let、const。

另一个误解是使用 var 声明的变量只会被提升,而 let 和 const 不会被提升。

但事实并非如此。根据定义,所有变量和函数声明都会被提升。但提升letconst方式略有不同。在块级作用域中,Let和会被提升;而在全局作用域中,则会被提升。(作用域是另一个重要概念,我们将在以后的文章中讨论)。constvar

console.log('myName',myName);
let myName = 'Javascript';
Enter fullscreen mode Exit fullscreen mode

如果你运行上面的代码,你会得到一个错误
Uncaught ReferenceError: myName is notdefined
这与使用 var 声明变量的情况不同。
等等,这是怎么回事?🤔
这里有一个术语叫做暂时死区(TDZ)
我们已经在理解一个科幻术语提升的过程中了,但这里又出现了另一个科幻术语,叫做 暂时死区 🙄。 那么,暂时死区到底是什么? 它是指从声明变量(使用)到初始化变量之间所花费的时间。 让我们回到相同的代码,看看为什么它显示引用错误。
JavaScript 提升

letconst

/*
  let myName;
  //Beginning of the temporal dead zone
  console.log(firstname); // ReferenceError as accessed in the TDZ.
let myName = 'Javascript'; // Ending of the temporal dead zone
*/
Enter fullscreen mode Exit fullscreen mode

建议使用Letand ,因为与 不同,除非必要,否则不存在执行范围之外的变量泄漏风险。要了解有关 var、let 和 const 声明的更多信息,请参阅此链接。constvar

函数提升

函数是 JavaScript 的基本构造块之一。
声明函数有多种方法。常见的声明方法如下:

  1. 函数声明
  2. 函数表达式
  3. 箭头函数

函数声明

greetings();
function greetings(){
    console.log('Hello from dev community')
}
Enter fullscreen mode Exit fullscreen mode

如果您运行此示例,它不会抛出任何错误,因为由于提升,问候语将在 javascript 引擎第一次运行时声明。

greetings();
function greetings(){
 console.log('First',message);
 var message = 'Hello from Dev Community';
 console.log('Second',message);
}
Enter fullscreen mode Exit fullscreen mode

如果你运行这段代码,控制台首先会显示:undefined因为函数内部声明的变量只会被提升到特定作用域(代码块)的顶部。所以代码会是:

greetings();
function greetings(){
 var message;
 console.log('First',message);
 message = 'Hello from Dev Community';
 console.log('Second',message);
}
Enter fullscreen mode Exit fullscreen mode

函数表达式

greetings(); // Ouput: TypeError: expression is not a function.

var greetings = function hoisting() {
  console.log('Hello from function expression?');
};
Enter fullscreen mode Exit fullscreen mode

JavaScript 返回 ,TypeError因为与函数声明不同,只有变量 被提升。当使用 var 声明的变量被提升时,它们会被赋予默认值undefined。JavaScript 随后会抛出错误,因为此时变量的值还不是一个函数。

箭头函数

greetings(); // Ouput: TypeError: expression is not a function.

const greetings = () => {
  console.log('Hello from arrow functions?');
};
Enter fullscreen mode Exit fullscreen mode

由于变量提升,这与函数表达式的作用相同。使用箭头函数或任何其他函数表达式时,我们必须始终在调用函数之前定义它。在声明之前访问变量通常是导致错误的根本原因。为了澄清这一点,需要澄清的是,

函数声明被提升

优先顺序

根据ECMAScript 第 10.5 节,函数声明始终比变量声明具有更高的优先级

var abc;
function abc(){}
console.log(typeof abc)
Enter fullscreen mode Exit fullscreen mode
function abcd(){}
var abcd
console.log(typeof abcd)
Enter fullscreen mode Exit fullscreen mode

如果您运行上述代码,无论您以何种顺序声明它,JavaScript 引擎始终会优先考虑函数声明而不是变量声明。

结论

让我们总结一下我们学到的东西

  • 提升是在给定的执行范围内,在赋值和初始化之前将变量和函数声明到内存空间中的过程。
  • 只有变量声明和函数声明会被提升。
  • const 和 let 将被提升,但在初始化之前无法读取或访问。
  • 在提升时,函数声明的优先级高于变量声明。

为了避免变量提升和错误,最好在访问变量和函数之前声明它们。这样可以避免控制台中充斥着大量的错误和未定义的警告。

我希望本文能阐明 JavaScript 中提升的工作原理。它听起来确实不复杂,但需要我们分解不同的用例,并尝试不同的场景才能理解其背后的工作原理。

感谢阅读这篇文章。祝您有美好的一天🙂。
下篇文章,我们一起探讨另一个 JavaScript 概念。

文章来源:https://dev.to/naveenchandar/javascript-hoisting-2pde
PREV
Package.json 文件解释!!!
NEXT
为什么在 2023 年仅使用 console.log 是大忌🚀