高阶函数
00:00
以函数为参数或返回值的编程模式
1. 高阶函数概述
1.1 定义
高阶函数(Higher-Order Function)是满足以下条件之一的函数:
- 接受一个或多个函数作为参数
- 返回一个函数作为结果
// 函数作为参数
function applyOperation(arr, operation) {
return arr.map(operation);
}
const doubled = applyOperation([1, 2, 3], (x) => x * 2);
console.log(doubled); // [2, 4, 6]
// 函数作为返回值
function createMultiplier(factor) {
return function (number) {
return number * factor;
};
}
const triple = createMultiplier(3);
console.log(triple(5)); // 15
1.2 为什么需要高阶函数
| 优势 | 说明 |
|---|---|
| 抽象 | 隐藏实现细节,关注”做什么”而非”怎么做” |
| 复用 | 将通用逻辑提取为高阶函数,减少重复代码 |
| 组合 | 通过函数组合构建复杂逻辑 |
| 声明式 | 代码更接近自然语言描述 |
2. 内置高阶函数
2.1 Array.prototype.map
const users = [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 },
{ name: 'Charlie', age: 35 },
];
const names = users.map((user) => user.name);
console.log(names); // ['Alice', 'Bob', 'Charlie']
2.2 Array.prototype.filter
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const evens = numbers.filter((n) => n % 2 === 0);
console.log(evens); // [2, 4, 6, 8, 10]
// 链式调用
const result = numbers.filter((n) => n % 2 === 0).map((n) => n ** 2);
console.log(result); // [4, 16, 36, 64, 100]
2.3 Array.prototype.reduce
// 求和
const sum = [1, 2, 3, 4, 5].reduce((acc, cur) => acc + cur, 0);
console.log(sum); // 15
// 统计词频
const words = ['apple', 'banana', 'apple', 'cherry', 'banana', 'apple'];
const wordCount = words.reduce((acc, word) => {
acc[word] = (acc[word] || 0) + 1;
return acc;
}, {});
// 管道函数
const pipe =
(...fns) =>
(x) =>
fns.reduce((v, f) => f(v), x);
const add1 = (x) => x + 1;
const double = (x) => x * 2;
const transform = pipe(add1, double);
console.log(transform(5)); // 12
2.4 其他内置高阶函数
| 方法 | 说明 | 返回值 |
|---|---|---|
forEach | 遍历执行 | undefined |
find | 查找第一个匹配 | 元素或 undefined |
findIndex | 查找第一个匹配索引 | 索引或 -1 |
some | 是否存在匹配 | boolean |
every | 是否全部匹配 | boolean |
sort | 排序 | 排序后的数组 |
flatMap | map + flat(1) | 新数组 |
3. 自定义高阶函数
3.1 函数组合
const compose =
(...fns) =>
(x) =>
fns.reduceRight((v, f) => f(v), x);
const pipe =
(...fns) =>
(x) =>
fns.reduce((v, f) => f(v), x);
const add10 = (x) => x + 10;
const multiply3 = (x) => x * 3;
const toString = (x) => `Result: ${x}`;
const compute = pipe(add10, multiply3, toString);
console.log(compute(5)); // "Result: 45"
3.2 记忆化
function memoize(fn) {
const cache = new Map();
return function (...args) {
const key = JSON.stringify(args);
if (cache.has(key)) return cache.get(key);
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
const fibonacci = memoize(function (n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
});
console.log(fibonacci(50)); // 12586269025
3.3 节流与防抖
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
function throttle(fn, interval) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= interval) {
lastTime = now;
fn.apply(this, args);
}
};
}
4. 性能考量
| 注意事项 | 说明 |
|---|---|
| 避免在渲染循环中创建函数 | 每次渲染创建新闭包增加 GC 压力 |
| 链式调用创建中间数组 | 大数据集考虑 reduce |
| 记忆化的内存开销 | 缓存会持续增长,需要清理策略 |