JS 中函数表达式和函数声明的真相
2024-02-11 23:40:09
JavaScript 中的函数表达式和函数声明是定义函数的两种主要方式。它们之间存在一些关键差异,包括声明提升、作用域和闭包行为。本文将深入探讨这些差异,帮助您更好地理解 JavaScript 中的函数。
声明提升
函数声明会在脚本执行之前提升到脚本顶部。这意味着可以在声明函数之前调用它。这是因为 JavaScript 引擎在执行脚本之前会先扫描整个脚本,并将所有函数声明提升到顶部。函数表达式不会提升,因此必须在声明之前定义它。
// 函数声明
function sayHello() {
console.log("Hello!");
}
// 函数表达式
const sayGoodbye = function() {
console.log("Goodbye!");
};
sayHello(); // "Hello!"
sayGoodbye(); // "Goodbye!"
在上面的示例中,函数声明 sayHello()
在执行脚本之前提升到顶部,因此可以在声明之前调用它。函数表达式 sayGoodbye()
不会提升,因此必须在声明之前定义它。
作用域
函数的作用域是指函数可以访问的变量的集合。函数的作用域由其所在的位置决定。函数声明的作用域是整个脚本,而函数表达式的作用域是它所在的花括号块。
// 函数声明
function sayHello() {
var message = "Hello!";
console.log(message);
}
// 函数表达式
const sayGoodbye = function() {
var message = "Goodbye!";
console.log(message);
};
sayHello(); // "Hello!"
sayGoodbye(); // "Goodbye!"
console.log(message); // ReferenceError: message is not defined
在上面的示例中,函数声明 sayHello()
的作用域是整个脚本,因此它可以访问变量 message
。函数表达式 sayGoodbye()
的作用域是它所在的花括号块,因此它只能访问变量 message
。当在函数表达式外部尝试访问变量 message
时,会抛出 ReferenceError。
闭包
闭包是指可以访问其创建函数中声明的变量的函数。闭包可以用来创建一个私有变量,或者在函数执行之后仍然可以访问变量。
function createCounter() {
var counter = 0;
return function() {
return ++counter;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
在上面的示例中,函数 createCounter()
返回一个函数,该函数可以访问变量 counter
。这意味着该函数是一个闭包。当调用函数 counter()
时,它会返回变量 counter
的当前值,然后将 counter
的值加一。
结论
函数表达式和函数声明是 JavaScript 中定义函数的两种主要方式。它们之间存在一些关键差异,包括声明提升、作用域和闭包行为。了解这些差异对于理解 JavaScript 中的函数非常重要。