JavaScript 中的一等函数
Source: Dev.to
介绍
对于学习 JavaScript 的开发者来说,一等函数(first‑class functions)这个术语经常出现在讨论和文档中。在 JavaScript 中,函数是 一等公民:它们被视为普通值。就像字符串可以存入变量或传递给其他函数一样,函数也可以被存储、传递并返回。
一等函数的核心概念
将函数存入变量
const washCarrot = function (carrot) {
return `${carrot} is now clean!`;
};
console.log(washCarrot('Orange carrot')); // "Orange carrot is now clean!"
将函数作为参数传递
function prepareVegetable(veggie, quantity, prepMethod) {
return prepMethod(veggie, quantity);
}
const chop = (veg, qty) => `Chopped ${qty} ${veg}`;
const steam = (veg, qty) => `Steamed ${qty} ${veg}`;
console.log(prepareVegetable('broccoli', 3, chop)); // "Chopped 3 broccoli"
console.log(prepareVegetable('carrots', 5, steam)); // "Steamed 5 carrots"
从函数返回函数
function createVeggieCounter(vegetable) {
return function (quantity) {
return `You have ${quantity} ${vegetable}`;
};
}
const countTomatoes = createVeggieCounter('tomatoes');
const countCucumbers = createVeggieCounter('cucumbers');
console.log(countTomatoes(12)); // "You have 12 tomatoes"
console.log(countCucumbers(8)); // "You have 8 cucumbers"
在对象中组织函数
const kitchenTasks = {
wash: (veggie) => `Washing ${veggie}`,
peel: (veggie) => `Peeling ${veggie}`,
slice: (veggie) => `Slicing ${veggie}`
};
console.log(kitchenTasks.wash('spinach')); // "Washing spinach"
实际应用
map、filter 等数组方法完全依赖一等函数,事件处理器、回调、Promise 以及许多函数式编程模式也是如此。
const vegetables = ['carrot', 'broccoli', 'spinach', 'tomato', 'cucumber'];
const upperCaseVeggies = vegetables.map(veggie => veggie.toUpperCase());
// ['CARROT', 'BROCCOLI', 'SPINACH', 'TOMATO', 'CUCUMBER']
const longNameVeggies = vegetables.filter(veggie => veggie.length > 6);
// ['broccoli', 'spinach', 'cucumber']
好处
一等函数为 JavaScript 带来了极大的灵活性。它们可以像其他数据一样被移动、转换和组合,从而实现更简洁、更模块化的代码。理解这一概念可以阐明许多 JavaScript 模式,并释放语言的全部威力。
潜在陷阱
同样的灵活性如果使用不当也会导致问题:
- 内存泄漏 – 未被移除的持久事件监听器。
- 回调地狱 – 深层嵌套的回调导致代码难以阅读。
- 意外闭包 – 函数捕获了超出预期的状态,产生细微错误。
- 性能问题 – 在循环或频繁调用的代码中创建大量函数实例。
了解这些风险有助于开发者负责任地使用一等函数。
结论
一等函数是现代 JavaScript 开发的基石。React 等框架、基于 Promise 的异步代码以及事件驱动编程都依赖于把函数当作值来对待。掌握这一概念能够让开发者编写出更具表现力、可维护性和强大的 JavaScript 代码。