函数提升
在 JavaScript 中,函数提升(Function Hoisting)是指在代码执行之前,函数声明会被提升到其所在作用域的顶部。这意味着你可以在函数声明之前调用该函数。
函数声明提升
函数声明会被提升到其所在作用域的顶部,因此你可以在函数声明之前调用该函数。
例如:
// 可以在函数声明之前调用函数
console.log(add(2, 3)); // 输出 5
// 函数声明
function add(a, b) {
return a + b;
}
在这个示例中,函数 add 的声明被提升到作用域的顶部,因此你可以在声明之前调用它。
函数表达式不提升
函数表达式不会被提升,这意味着你不能在函数表达式之前调用该函数。
例如:
try {
console.log(subtract(5, 3)); // 会抛出 TypeError: subtract is not a function
} catch (e) {
console.error(e);
}
// 函数表达式
const subtract = function(a, b) {
return a - b;
};
在这个示例中,函数表达式 subtract 不会被提升,因此在声明之前调用它会导致错误。
提升的作用域
函数提升只在其所在的作用域内有效。例如,在函数内部声明的函数只会在该函数的作用域内被提升。
function outer() {
console.log(inner()); // 输出 "Hello from inner"
function inner() {
return "Hello from inner";
}
}
outer();
在这个示例中,inner 函数的声明被提升到 outer 函数的顶部,因此你可以在 inner 函数声明之前调用它。
类提升
在 JavaScript 中,类提升(Class Hoisting)与函数提升不同。虽然类声明在其所在的作用域内被提升,但类本身不会被初始化,直到执行到类声明的那一行代码。这意味着你不能在类声明之前访问或实例化该类。
类声明提升但不初始化
类声明会被提升到其所在作用域的顶部,但类不会被初始化。
类声明具有与 let 和 const 相同的 暂时性死区 限制。在类声明之前访问或实例化类会导致 ReferenceError。
例如类似声明:
try {
const instance = new MyClass(); // 会抛出 ReferenceError: Cannot access 'MyClass' before initialization
} catch (e) {
console.error(e);
}
// 类声明
class MyClass {
constructor() {
this.name = "MyClass";
}
}
const instance2 = new MyClass(); // 正常工作
console.log(instance2.name); // 输出 "MyClass"
在这个示例中,类 MyClass 的声明被提升到作用域的顶部,但在声明之前访问或实例化该类会导致 ReferenceError。
类表达式不提升
与函数表达式类似,类表达式也不会被提升。这意味着你不能在类表达式之前访问或实例化该类。
例如:
try {
const instance = new MyClass(); // 会抛出 ReferenceError: MyClass is not defined
} catch (e) {
console.error(e);
}
// 类表达式
const MyClass = class {
constructor() {
this.name = "MyClass";
}
};
const instance2 = new MyClass(); // 正常工作
console.log(instance2.name); // 输出 "MyClass"
在这个示例中,类表达式 MyClass 不会被提升,因此在声明之前访问或实例化该类会导致 ReferenceError。
参考
提升
https://developer.mozilla.org/zh-CN/docs/Glossary/Hoisting