JavaScript - 函数提升



函数提升

在 JavaScript 中,函数提升是一种默认行为,其中函数声明在代码执行之前被移动到其局部作用域的顶部。因此,您可以在其作用域中调用函数,即使它在之后才声明。需要注意的是,只有声明会被提升,初始化不会被提升。因此,变量或函数应该在使用之前进行初始化。

与函数提升类似,变量提升也是一种默认行为,其中变量声明被移动到其局部作用域的顶部。我们可以在函数声明之前使用该函数。

让我们考虑以下 JavaScript 代码。

add(5,10); // 15
function add(x, y){
   return x + y;
}

在上面的 JavaScript 代码中,函数 add 在其声明之前被调用。这是因为 JavaScript 解释器将函数声明提升到作用域的顶部。因此,上面的代码等价于 –

function add(x, y){
   return x + y;
}
add(5,10); // 15

函数提升仅适用于函数声明,而不适用于函数表达式。因此,如果函数使用函数表达式定义,则它不会被提升到顶部。

add(5,10); // ReferenceError: Cannot access 'add' before initialization
const add = function (x, y){
   return x + y;
}

让我们编写一些完整的 JavaScript 函数提升示例。

示例:函数提升

在下面的示例中,我们定义了 printMessage() 函数,打印其被调用的位置。

此外,我们在函数定义之前和之后调用 printMessage() 函数。它在没有错误的情况下打印输出,因为函数被提升到其作用域的顶部。

<html>
<body>
   <p id = "output"> </p>
   <script>
      printMessage("Top");        
      function printMessage(pos) {
         document.getElementById("output").innerHTML += 
         "The function is called from the " + pos + "<br/>";
      }        
      printMessage("Bottom");
   </script>
</body>
</html>

输出

The function is called from the Top
The function is called from the Bottom

示例

在下面的示例中,我们在 'if' 块内定义了函数。因此,函数被提升到 'if' 块的顶部,并且您只能在 'if' 块内在其初始化之前执行该函数。

您无法在 'if' 块外部访问该函数。

<html>
<body>
   <p id = "output"> </p>
   <script>
      // test("Top"); // Out of scope
      if (1) {
         test("Top"); // In the same scope
         function test(pos) {
            document.getElementById("output").innerHTML += 
            "The function is called from the " + pos + "<br/>";
         }
         test("Bottom"); // In the same scope
      }
   </script>
</body>
</html>

输出

The function is called from the Top
The function is called from the Bottom

提升是 JavaScript 中非常重要的行为。但是,始终建议在代码开头声明函数或变量。因为 JavaScript 总是按声明顺序、然后初始化顺序、最后使用顺序来解释代码。

JavaScript 变量提升

JavaScript 的提升行为默认将变量声明移动到变量作用域的顶部。在 JavaScript 中,使用 'var' 关键字声明的变量会被提升到其作用域的顶部,但使用 'let' 和 'const' 关键字声明的变量不会被提升到顶部。

例如,

var x = y;
var y;

上面的代码类似于下面的代码,因为变量声明被提升到顶部。

var y;
var x = y;

让我们通过以下示例了解变量提升。

示例:变量提升

在下面的示例中,我们初始化了变量 y,在输出中打印了其值,并在最后声明了它。下面的代码在没有错误的情况下打印了一个值,因为变量 y 在全局作用域中被提升到顶部。

<html>
<head>
   <title> JavaScript - Variable Hoisting </title>
</head>
<body>
   <p id = "output"> </p>
   <script>
      y = 10;
      document.getElementById("output").innerHTML = 
	  "The value of the y is : " + y;
      var y;
   </script>
</body>
</html>

输出

The value of the y is : 10

示例:带有函数的变量提升

在下面的示例中,我们定义了 printNum() 函数。在 printNum() 函数中,我们初始化了变量 y,打印了其值,并在之后声明了它。

变量 y 被提升到函数的顶部,因此您可以在其声明之前访问它,但您无法在函数外部访问它。

<html>
<head>
   <title> JavaScript - Variable Hoisting with function </title>
</head>
<body>
   <p id = "output"> </p>
   <script>
      const output = document.getElementById("output");
      function printNum() {
         y = 20;
         output.innerHTML += "The value of the variable y is : " + y;
         var y; // Function scope
      }
      printNum();
      // Variable Y can't be accessible here
   </script>
</body>
</html>

输出

The value of the variable y is : 20

但是,变量初始化不会被提升到块的顶部。

示例:变量初始化不会提升

下面的示例演示了变量会在顶部提升,但变量初始化不会。在这里,我们在没有初始化变量 x 的情况下打印它。因此,它在输出中打印“undefined”。

<html>
<body>
   <p id = "output"> </p>
   <script>
      var x;
      document.getElementById("output").innerHTML = "x is -> " + x;
      x = 10;
   </script>
</body>
</html>

输出

x is -> undefined

示例:使用 let 和 const 关键字提升

下面的示例演示了使用“let”和“const”关键字声明的变量不会提升到顶部。因此,您始终需要在使用它之前定义它。

我们使用“try…catch”块来处理错误。在输出中,用户可以观察到当我们访问使用“let”关键字声明的变量时,以下代码给出的错误。

<html>
<head>
   <title> Hoisting with let and const </title>
</head>
<body>
   <p id = "output"> </p>
   <script>
      const output = document.getElementById("output");
      try {
         x = 10;
         output.innerHTML += "The value of x is -> " + x;
         let x;
      }catch (error) {
         output.innerHTML += error.message;
      }
   </script>
</body>
</html>

输出

Cannot access 'x' before initialization
广告