JavaScript 函数表达式
什么是函数表达式?
在JavaScript中,函数表达式是创建函数的另一种方式。与函数声明不同,函数表达式可以将函数赋值给变量,将它们存储在对象的属性中,作为参数传递给其他函数,甚至立即执行。
函数表达式的基本语法如下:
javascript
const myFunction = function(parameters) {
// 函数体
return result;
};
备注
函数表达式与函数声明的主要区别在于:函数表达式可以是匿名的,它不会被提升(hoisted),只有在代码执行到它的位置时才会被创建。
函数表达式与函数声明的区别
让我们比较一下函数表达式和函数声明:
函数声明
javascript
function sayHello(name) {
return `Hello, ${name}!`;
}
// 可以在声明前调用
console.log(sayHello("Alex")); // 输出: Hello, Alex!
函数表达式
javascript
const sayHi = function(name) {
return `Hi, ${name}!`;
};
// 只能在定义后调用
console.log(sayHi("Alex")); // 输出: Hi, Alex!
如果你尝试在定义前调用函数表达式,会得到错误:
javascript
console.log(sayBye("Alex")); // 错误: sayBye is not defined
const sayBye = function(name) {
return `Bye, ${name}!`;
};
函数表达式的类型
1. 匿名函数表达式
最常见的函数表达式是匿名的,即没有名称:
javascript
const calculate = function(a, b) {
return a + b;
};
console.log(calculate(5, 3)); // 输出: 8
2. 命名函数表达式
函数表达式也可以有名称,这在递归或调试时特别有用:
javascript
const factorial = function fact(n) {
if (n <= 1) return 1;
return n * fact(n - 1);
};
console.log(factorial(5)); // 输出: 120
注意,函数名fact
只在函数内部可见,外部不能直接使用。
3. 箭头函数表达式(ES6)
ES6引入了箭头函数,它是函数表达式的简写形式:
javascript
const add = (a, b) => a + b;
console.log(add(5, 3)); // 输出: 8
对于多行函数体,需要使用花括号并明确返回:
javascript
const getFullName = (firstName, lastName) => {
const fullName = `${firstName} ${lastName}`;
return fullName;
};
console.log(getFullName("John", "Doe")); // 输出: John Doe
函数表达式的应用场景
1. 作为回调函数
函数表达式常用作回调函数,特别是在事件处理和异步操作中:
javascript
// 事件监听器
document.getElementById("button").addEventListener("click", function() {
alert("Button was clicked!");
});
// setTimeout中使用
setTimeout(function() {
console.log("This message appears after 2 seconds");
}, 2000);
2. 立即执行函数表达式(IIFE)
IIFE是一种在定义后立即执行的函数表达式,用于创建私有作用域:
javascript
(function() {
const privateVar = "I am private";
console.log(privateVar); // 输出: I am private
})();
// console.log(privateVar); // 错误: privateVar is not defined
3. 函数工厂
函数表达式可以用来创建函数工厂,即返回新函数的函数:
javascript
function createMultiplier(factor) {
return function(number) {
return number * factor;
};
}
const double = createMultiplier(2);
const triple = createMultiplier(3);
console.log(double(5)); // 输出: 10
console.log(triple(5)); // 输出: 15
4. 闭包
函数表达式经常用于创建闭包,这使得函数可以访问其外部函数的变量:
javascript
function counter() {
let count = 0;
return function() {
count++;
return count;
};
}
const increment = counter();
console.log(increment()); // 输出: 1
console.log(increment()); // 输出: 2
console.log(increment()); // 输出: 3
函数表达式的高级应用
高阶函数
函数表达式使得函数可以作为值传递,这是高阶函数的基础:
javascript
// map接收一个函数作为参数
const numbers = [1, 2, 3, 4];
const squared = numbers.map(function(num) {
return num * num;
});
console.log(squared); // 输出: [1, 4, 9, 16]
// 使用箭头函数可以更简洁
const cubed = numbers.map(num => num * num * num);
console.log(cubed); // 输出: [1, 8, 27, 64]
函数柯里化
使用函数表达式实现柯里化(将接受多个参数的函数转变为接受一个单一参数的函数序列):
javascript
function curry(fn) {
return function(a) {
return function(b) {
return fn(a, b);
};
};
}
const add = (a, b) => a + b;
const curriedAdd = curry(add);
console.log(curriedAdd(5)(3)); // 输出: 8
实际案例:创建一个简单的表单验证器
下面是一个使用函数表达式创建表单验证器的实际案例:
javascript
// 创建验证器
const createValidator = function() {
const validators = [];
// 添加验证规则
return {
addRule: function(field, validationFn, errorMessage) {
validators.push({
field: field,
validate: validationFn,
message: errorMessage
});
},
// 验证表单
validate: function(formData) {
const errors = [];
validators.forEach(function(validator) {
const value = formData[validator.field];
if (!validator.validate(value)) {
errors.push({
field: validator.field,
message: validator.message
});
}
});
return {
isValid: errors.length === 0,
errors: errors
};
}
};
};
// 使用验证器
const formValidator = createValidator();
// 添加验证规则
formValidator.addRule('username',
value => value && value.length >= 3,
'用户名至少需要3个字符'
);
formValidator.addRule('email',
value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
'请输入有效的邮箱地址'
);
// 验证数据
const userData = {
username: 'ab',
email: 'invalid-email'
};
const result = formValidator.validate(userData);
console.log(result.isValid); // 输出: false
console.log(result.errors);
// 输出: [
// { field: 'username', message: '用户名至少需要3个字符' },
// { field: 'email', message: '请输入有效的邮箱地址' }
// ]
总结
函数表达式是JavaScript中创建和使用函数的强大方式,它提供了灵活性和多种用途:
- 可以创建匿名函数或命名函数
- 不会被提升,需要在定义后使用
- 可以作为值传递给其他函数
- 用于创建立即执行函数表达式(IIFE)
- 在闭包、回调和高阶函数中发挥重要作用
- ES6中的箭头函数提供了更简洁的函数表达式语法
掌握函数表达式将使你能够编写更灵活、更模块化的JavaScript代码。
练习
- 创建一个函数表达式,接受一个数字数组并返回所有偶数的新数组。
- 编写一个IIFE,创建一个计数器并在控制台输出1到5。
- 使用箭头函数和数组方法
filter
、map
和reduce
,创建一个函数表达式,计算一个数字数组中所有正数的平方和。 - 创建一个函数工厂,根据不同的折扣率生成计算折扣价格的函数。
进一步学习
要更深入地了解JavaScript函数表达式,可以参考:
- MDN Web Docs的函数表达式
- 学习闭包、高阶函数和函数式编程概念
- 研究更多ES6箭头函数的用法和优势