理解高阶函数的定义与核心特征
掌握 JavaScript 中常用的数组高阶方法(map、filter、reduce 等)
能够使用高阶函数实现函数组合、柯里化和记忆化
理解高阶函数如何提升代码的可复用性、模块化与声明式风格
在实际开发中合理运用高阶函数编写更简洁、健壮的代码
高阶函数是指满足以下任一条件的函数:
接收一个或多个函数作为参数
返回一个函数作为结果
核心思想:函数是一等公民,可以像数字、字符串一样被传递、赋值、返回。
function greet() {
console.log("Hello, World!");
}
function repeat(action) {
action();
action();
}
repeat(greet); // 输出两次 "Hello, World!"repeat 是高阶函数(接收函数 action 作为参数)
greet 是回调函数(Callback)
这些方法是函数式编程的基石,强调不可变性(不修改原数组)和声明式风格。
map()转换数组,详情请参考《JavaScript 高阶函数 map》
对每个元素应用函数,返回新数组。
const numbers = [1, 2, 3, 4, 5];
const squares = numbers.map(num => num * num);
console.log(squares); // [1, 4, 9, 16, 25]特点:
返回新数组,长度与原数组相同
原数组不变(不可变性)
filter()筛选元素,详情请参考《JavaScript 高阶函数 filter》
保留满足条件的元素。
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // [2, 4]特点:
返回新数组,长度 ≤ 原数组
条件为 true 的元素被保留
reduce()归约聚合
将数组“压缩”为单个值(如求和、拼接等)。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // 15acc:累加器(accumulator)
curr:当前元素
0:初始值(可选,但建议显式提供)
应用场景:求和、求积、扁平化数组、统计计数等。
forEach()执行副作用
对每个元素执行操作(如打印、DOM 操作),不返回新数组。
[1, 2, 3].forEach(num => console.log(num * 2));
// 输出:2, 4, 6注意:forEach 不能链式调用,也不支持 break/continue。
find()查找首个匹配项,详情请参考《JavaScript 高阶函数 find》
返回第一个满足条件的元素,否则 undefined。
const users = [{id: 1, name: 'Alice'}, {id: 2, name: 'Bob'}];
const user = users.find(u => u.id === 2);
console.log(user); // {id: 2, name: 'Bob'}some() 与 every()逻辑判断,详情请参考《JavaScript every 与 some 的区别》
const nums = [1, 2, 3, -1];
console.log(nums.some(n => n < 0)); // true
console.log(nums.every(n => n > 0)); // false将多个函数串联执行:f(g(x))
function add(x) { return x + 2; }
function mul(x) { return x * 3; }
function compose(f, g) {
return function(x) {
return f(g(x));
};
}
const result = compose(add, mul)(4); // add(mul(4)) = add(12) = 14
console.log(result); // 14优势:构建复杂逻辑时保持代码清晰、可测试、可复用。
将多参函数转为一系列单参函数,利用闭包保存中间状态。
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // 10
console.log(double(7)); // 14应用:创建专用工具函数(如 fetchUserById = fetchUser.bind(null, 'user'))
缓存函数结果,避免重复计算。
function memoize(fn) {
const cache = {};
return function(arg) {
if (cache[arg] !== undefined) {
return cache[arg];
}
const result = fn(arg);
cache[arg] = result;
return result;
};
}
function slowCompute(n) {
console.log("Computing...");
return n * 2;
}
const fastCompute = memoize(slowCompute);
console.log(fastCompute(5)); // Computing... 10
console.log(fastCompute(5)); // 10(直接从缓存读取)适用场景:递归(如斐波那契)、昂贵计算、API 请求缓存。
控制流程解耦
function greet(name, callback) {
console.log("Hello, " + name);
callback();
}
function sayGoodbye() {
console.log("Goodbye!");
}
greet("Coder", sayGoodbye);
// 输出:
// Hello, Coder
// Goodbye!优势:将“问候”与“告别”逻辑分离,提高复用性。
创建函数工厂
function createMultiplier(factor) {
return function(num) {
return num * factor;
};
}
const triple = createMultiplier(3);
console.log(triple(4)); // 12利用闭包捕获 factor
实现配置化函数生成
声明式数据处理
// 传统 for 循环(命令式)
const doubled = [];
for (let i = 0; i < arr.length; i++) {
doubled.push(arr[i] * 2);
}
// 使用 map(声明式)
const doubled = arr.map(x => x * 2);声明式优势:
更易读、更少出错
自动处理边界(如空数组)
支持链式调用:
arr
.filter(x => x > 0)
.map(x => x * 2)
.reduce((a, b) => a + b, 0);以下代码输出什么?为什么?
const arr = [1, 2, 3];
arr.forEach(x => x * 2);
console.log(arr);如何用 reduce 实现 map 和 filter 的功能?尝试写出通用版本。