Javascript 简明教程

JavaScript - Function Hoisting

Function Hoisting

在 JavaScript 中的 function hoisting 是默认行为,在此行为中, function declarations 在执行代码之前移至其局部作用域的顶部。因此,您可以在函数声明之前在其作用域中调用它。需要注意的是,仅提升声明,而不提升初始化。因此,变量或函数在使用之前应已初始化。

The function hoisting in JavaScript is a default behavior in which function declarations are moved at the top of their local scope before execution of the code. So, you can call the function in its scope before it is declared. It’s important to notice that only declaration is hoisted not the initialization. So the variables or functions should have been initialized before they are used.

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

Similar to the function hoisting, the variable hoisting is also a default behavior in which the variable declarations are moved at the top of their local scope. We can use the function before it has been declared.

让我们看以下 JavaScript 代码。

Let’s consider the following JavaScript code.

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

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

In the above JavaScript code, the function add is called before it’s declaration. This is possible because JavaScript interpreter hoists the function declaration to the top of the scope. So the above code is equivalent to –

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

函数提升仅适用于 function declaration ,而不适用于 function expression 。因此,如果使用函数表达式定义函数,则不会将其提升到顶部。

The function hoisting only works with function declaration not with function expression. So, if the function is defined using the function expression,., it is not hoisted at the top.

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

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

Let’s write some complete JavaScript examples of function hoisting.

Example: Function Hoisting

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

In the example below, we have defined the printMessage() function, printing the position from where it is called.

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

Also, we call the printMessage() function before and after the function definition. It prints the output without any error as the function is hoisted at the top of its scope.

<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

Example

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

In the example below, we have defined the function inside the 'if' block. So, the function is hoisted at the top of the 'if' block, and you can execute the function only inside the 'if' block before its initialization.

您不能在“if”块外部访问该函数。

You can’t access the function outside the 'if' block.

<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 始终按声明顺序、然后按初始化顺序,最后按使用顺序解释代码。

The hoisting is very important behavior in JavaScript. But it is always advisable to declare the function or variable at the beginning of the code. Since JavaScript always interprets the code in sequence of declaration, then initialization and then usage.

JavaScript Variable Hoisting

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

The hoisting behaviors of JavaScript move the variables declaration to the top of the variable’s scope by default. In JavaScript, variables declared with the 'var' keyword are hoisted at the top of its scope, but variables declared with the 'let' and 'const' keyword is not hoisted at the top.

例如,

For example,

var x = y;
var y;

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

The above code is similar to the below code, as the variables declaration is hoisted at the top.

var y;
var x = y;

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

Let’s understand the variable hoisting by following examples.

Example: Variable Hoisting

在下面的示例中,我们初始化了变量 y,在输出中打印了它的值,并在最后声明了它。由于在全局作用域的顶部提升了变量 y,因此下面的代码会打印一个值,而不会出现任何错误。

In the example below, we have initialized the variable y, printed its value in the output, and declared it at the end. The below code prints a value without any error, as variable y is hoisted at the top in the global scope.

<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

Example: Variable Hoisting with Function

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

In the example below, we have defined the printNum() function. In the printNum() function, we have initialized the variable y, printed its value, and declared it afterward.

变量 y 在函数顶部被提升,以便你可以在它的声明之前访问它,但你不能在函数外部访问它。

The variable y is hoisted at the top of the function so you can access it before its declaration, but you can’t access it outside the function.

<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

然而,变量初始化没有被提升到块的顶部。

However, variable initialization is not hoisted at the top of the block.

Example: variable initialization is not hoisted

下面的示例演示了变量被提升到顶部,但变量初始化没有。在这里,我们打印变量 x,而没有初始化它。因此,它在输出中打印出“未定义”。

The example below demonstrates that the variable is hoisted at the top, but the variable initialization is not. Here, we print the variable x without initialization of it. So, it prints the 'undefined' in the output.

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

Example: Hoisting with let and const keywords

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

The below example demonstrates that the variable declared with the 'let' and 'const' keywords are not hoisted at the top. So, you always need to define it before using it.

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

We used the 'try…catch' block to handle the error. In the output, users can observe the error the below code gives when we access the variable declared with the 'let' keyword.

<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