函数表达式与函数声明的区别与应用
2023-10-08 11:45:11
函数是 JavaScript 中最重要的构建块之一,它允许您将代码组织成更小的、可重用的单元。函数可以声明或表达式来创建,它们之间存在一些关键差异。
函数声明
函数声明使用 function
和函数名来声明函数,后面跟一对圆括号和函数体。函数体由一对花括号括起来,其中包含函数的代码。
function greet(name) {
console.log(`Hello, ${name}!`);
}
函数声明可以出现在脚本的任何位置,并且会在脚本执行时被解析。这意味着函数在被调用之前必须声明。
函数表达式
函数表达式使用 function
关键字和一对圆括号来声明函数,后面跟一对花括号和函数体。函数表达式可以分配给变量、作为参数传递给其他函数,或者作为函数返回值。
const greet = function (name) {
console.log(`Hello, ${name}!`);
};
函数表达式可以在脚本的任何位置创建,并且在执行到该行时被解析。这意味着函数可以在被调用之前声明。
函数声明和函数表达式的区别
函数声明和函数表达式之间的主要区别在于它们的声明和执行顺序。函数声明在脚本执行时被解析,而函数表达式在执行到该行时被解析。
这意味着函数声明可以在脚本的任何位置声明,并且会在脚本执行时被解析。而函数表达式只能在脚本的当前位置声明,并且会在执行到该行时被解析。
变量提升
函数声明和函数表达式的一个重要区别是变量提升。变量提升是指在脚本执行时,所有变量声明都会被提升到脚本的最顶部。这意味着函数声明中的变量在脚本执行时会被提升到全局作用域,而函数表达式中的变量只会被提升到函数体内。
// 函数声明
function greet(name) {
console.log(`Hello, ${name}!`);
}
// 函数表达式
const greet = function (name) {
console.log(`Hello, ${name}!`);
};
console.log(greet); // undefined
在上面的示例中,函数声明中的 greet
变量在脚本执行时会被提升到全局作用域,因此 console.log(greet)
会输出函数声明。而函数表达式中的 greet
变量只会被提升到函数体内,因此 console.log(greet)
会输出 undefined
。
作用域
函数声明和函数表达式的一个区别是作用域。函数声明的作用域是全局作用域或函数体,而函数表达式的作用域是函数体。
// 函数声明
function greet(name) {
console.log(`Hello, ${name}!`);
}
// 函数表达式
const greet = function (name) {
console.log(`Hello, ${name}!`);
};
if (true) {
// 函数声明
function greet(name) {
console.log(`Hello, ${name}!`);
}
// 函数表达式
const greet = function (name) {
console.log(`Hello, ${name}!`);
};
}
console.log(greet); // 输出函数声明
在上面的示例中,函数声明中的 greet
变量在脚本执行时会被提升到全局作用域,因此 console.log(greet)
会输出函数声明。而函数表达式中的 greet
变量只会被提升到函数体内,因此 console.log(greet)
会输出 undefined
。
词法作用域和动态作用域
函数声明和函数表达式的一个区别是词法作用域和动态作用域。词法作用域是指函数的作用域由函数的声明位置决定,而动态作用域是指函数的作用域由函数的调用位置决定。
// 词法作用域
function greet(name) {
console.log(`Hello, ${name}!`);
function innerGreet(name) {
console.log(`Hello, ${name}!`);
}
innerGreet("John"); // 输出 "Hello, John!"
}
greet("Mary"); // 输出 "Hello, Mary!"
在上面的示例中,函数 greet
和函数 innerGreet
都在函数 greet
的作用域内。这意味着函数 innerGreet
可以访问函数 greet
的变量 name
。
// 动态作用域
const greet = function (name) {
console.log(`Hello, ${name}!`);
const innerGreet = function (name) {
console.log(`Hello, ${name}!`);
};
innerGreet("John"); // 输出 "Hello, undefined!"
};
greet("Mary"); // 输出 "Hello, Mary!"
在上面的示例中,函数 greet
和函数 innerGreet
都在函数 greet
的作用域内。但是,函数 innerGreet
只能访问函数 greet
的变量 name
,而不能访问函数 greet
的变量 Mary
。
this
函数声明和函数表达式的一个区别是 this
。this
关键字是指当前执行的函数的作用域对象。在函数声明中,this
总是指向全局对象。而在函数表达式中,this
总是指向调用函数的作用域对象。
// 函数声明
function greet() {
console.log(`Hello, ${this.name}!`);
}
greet(); // 输出 "Hello, undefined!"
// 函数表达式
const greet = function () {
console.log(`Hello, ${this.name}!`);
};
greet(); // 输出 "Hello, undefined!"
在上面的示例中,函数声明中的 this
总是指向全局对象,因此 console.log(this.name)
会输出 undefined
。而函数表达式中的 this
总是指向调用函数的作用域对象,因此 console.log(this.name)
会输出 undefined
。
变量绑定
函数声明和函数表达式的一个区别是变量绑定。函数声明中的变量在函数执行时被绑定到函数体,而函数表达式中的变量在函数调用时被绑定到函数体。
// 函数声明
function greet(name) {
let message = "Hello, " + name + "!";
return message;
}
const greeting = greet("John"); // 输出 "Hello, John!"
console.log(message); // ReferenceError: message is not defined
在上面的示例中,函数声明中的 message
变量在函数执行时被绑定到函数体,因此 console.log(message)
会输出 ReferenceError: message is not defined
。
// 函数表达式
const greet = function (name) {
let message = "Hello, " + name + "!";
return message;
};
const greeting = greet("John"); // 输出 "Hello, John!"
console.log(message); // ReferenceError: message is not defined
在上面的示例中,函数表达式中的 message
变量在函数调用时被绑定到函数体,因此 console.log(message)
会输出 ReferenceError: message is not defined
。
块级作用域
函数声明和函数表达式的一个区别是块级作用域。块级作用域是指变量的作用域由变量的声明位置决定。在函数声明中,变量在函数体中声明,因此变量的作用域是函数体。而在函数表达式中,变量在函数体中声明,因此变量的作用域是函数体。
// 函数声明
function greet() {
{
let name = "John";
console.log(`Hello, ${name}!`); // 输出 "Hello, John!"
}
console.log(`Hello, ${name}!`); // ReferenceError: name is not defined
}
greet();
在上面的示例中,函数声明中的 name
变量在函数体中声明,因此变量的作用域是函数体。这意味着变量 name
只在函数体内有效,而在函数体外无法访问。
// 函数表达式
const greet = function () {
{
let name = "John";
console.log(`Hello, ${name}!`); // 输出 "Hello, John!"
}
console.log(`Hello, ${name}!`); // ReferenceError: name is not defined
};
greet();
在上面的示例中,函数表达式中的 name
变量在函数体中声明,因此变量的作用域是函数体。这意味着变量 name
只在函数体内有效,而在函数体外无法访问。
全局作用域
函数声明和函数表达式的一个区别是全局