JavaScript 中的函数提升是一种默认行为,即函数声明会在代码执行之前被移动到它们所在作用域的顶部。因此,你可以在函数声明之前调用该函数。需要注意的是,只有声明会被提升,初始化不会。所以变量或函数应该在使用前被初始化。
类似于函数提升,变量提升也是一种默认行为,即变量声明会被移动到它们所在作用域的顶部。我们可以在函数声明之前使用它。
让我们考虑以下 JavaScript 代码。
add(5,10);
function add(x, y){
return x + y;
}
在上述 JavaScript 代码中,函数 add
在其声明之前被调用。这是因为 JavaScript 解释器将函数声明提升到了作用域的顶部。所以上述代码等价于:
function add(x, y){
return x + y;
}
add(5,10);
函数提升仅适用于函数声明而不适用于函数表达式。因此,如果函数是使用函数表达式定义的,则不会被提升到顶部。
add(5,10);
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
块之外访问该函数。
<html>
<body>
<p id = "output"> </p>
<script>
if (1) {
test("Top");
function test(pos) {
document.getElementById("output").innerHTML +=
"The function is called from the " + pos + "<br/>";
}
test("Bottom");
}
</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;
}
printNum();
</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