跳到主要内容

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代码。

练习

  1. 创建一个函数表达式,接受一个数字数组并返回所有偶数的新数组。
  2. 编写一个IIFE,创建一个计数器并在控制台输出1到5。
  3. 使用箭头函数和数组方法filtermapreduce,创建一个函数表达式,计算一个数字数组中所有正数的平方和。
  4. 创建一个函数工厂,根据不同的折扣率生成计算折扣价格的函数。
进一步学习

要更深入地了解JavaScript函数表达式,可以参考:

  • MDN Web Docs的函数表达式
  • 学习闭包、高阶函数和函数式编程概念
  • 研究更多ES6箭头函数的用法和优势