Javascript 简明教程
JavaScript - Function Hoisting
Function Hoisting
在 JavaScript 中的 function hoisting 是默认行为,在此行为中, function declarations 在执行代码之前移至其局部作用域的顶部。因此,您可以在函数声明之前在其作用域中调用它。需要注意的是,仅提升声明,而不提升初始化。因此,变量或函数在使用之前应已初始化。
变量提升与函数提升类似,变量提升也是一种默认行为,在此行为中,变量声明移至其局部作用域的顶部。我们可以在函数声明之前使用此函数。
让我们看以下 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
函数提升仅适用于 function declaration ,而不适用于 function expression 。因此,如果使用函数表达式定义函数,则不会将其提升到顶部。
add(5,10); // ReferenceError: Cannot access 'add' before initialization
const add = function (x, y){
return x + y;
}
让我们编写一些函数提升的完整 JavaScript 示例。
Example: Function Hoisting
在下面的示例中,我们定义了 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
Example
在下面的示例中,我们在“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 Variable Hoisting
JavaScript 的提升行为默认将变量声明移至变量作用域的顶部。在 JavaScript 中,使用“var”关键字声明的变量会被提升到其作用域的顶部,但使用“let”和“const”关键字声明的变量不会被提升到顶部。
例如,
var x = y;
var y;
上面的代码与下面的代码类似,因为变量声明被提升到顶部。
var y;
var x = y;
让我们通过以下示例来了解变量提升。
Example: Variable Hoisting
在下面的示例中,我们初始化了变量 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
Example: Variable Hoisting with Function
在下面的示例中,我们定义了 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
然而,变量初始化没有被提升到块的顶部。
Example: variable initialization is not hoisted
下面的示例演示了变量被提升到顶部,但变量初始化没有。在这里,我们打印变量 x,而没有初始化它。因此,它在输出中打印出“未定义”。
<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”关键字声明的变量不被提升到顶部。因此,你总需要在使用之前定义它。
我们使用“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