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
廣告