红宝书第八讲:箭头函数与高阶函数:厨房工具与智能菜谱的对比
红宝书第八讲:箭头函数与高阶函数:厨房工具与智能菜谱的对比
资料取自《JavaScript高级程序设计(第5版)》。
查看总目录:红宝书学习大纲
一、箭头函数:快捷操作的切片刀
1. 基础语法特点
箭头函数是简洁版的函数表达式,特别适合简单操作,如切菜工具:
- 省略 function 关键字:使用
=>
代替 - 单行时省略 return:自动返回结果
代码对比:
// 传统函数表达式 (切菜刀)
const 切菜刀 = function(菜) { return 菜.slice(); };
// 箭头函数 (多功能切片器)
const 切片器 = (菜) => 菜.slice();
适用场景:
- 过滤菜谱(配合高阶函数)
const 食材 = ["西兰花", "胡萝卜"]; const 切好的 = 食材.map(菜 => 菜 + "片"); // ["西兰花片", "胡萝卜片"]
注意限制:
- 没有自己的
this
→ 继承父级上下文(如按钮点击处理需谨慎)
二、高阶函数:智能菜谱加工机
核心定义:接收/返回函数的函数,像自动处理食材的机器:
典型例子(资料6所示)1:
-
筛选合格食材(filter):
const 菜品 = [120, 80, 150]; const 高价菜 = 菜品.filter(价格 => 价格 > 100); // [120, 150]
-
检查食材达标(every):
const 是否全合格 = 菜品.every(价格 => 价格 > 50); // true(全部>50)
-
转换处理步骤(map):
const 涨价后 = 菜品.map(价格 => 价格 * 1.1); // [132, 88, 165]
三、经典组合:箭头+高阶函数
实战:优化订单处理
const 订单 = [
{ 菜品: "牛排", 价格: 200 },
{ 菜品: "沙拉", 价格: 40 }
];
// 步骤1:过滤高价菜品(filter)
const 高价菜品 = 订单.filter(item => item.价格 > 100);
// [{牛排:200}]
// 步骤2:计算总价(reduce)
const 总价 = 订单.reduce((总和, item) => 总和 + item.价格, 0);
// 240
四、避坑指南
箭头函数陷阱:
- 错误用法:对象方法中(丢失this)
const 厨房 = { 温度: 180℃, 预热: () => console.log(this.温度) // ❌ 输出undefined(this指向全局) }; 厨房.预热(); // 正确:用传统函数[^1] 预热() { console.log(this.温度); }
高阶函数注意:
- 回调函数参数顺序 → (元素, 索引, 原数组)
[1,2,3].filter((num, index) => index % 2 === 0); // [1,3](保留偶数索引项)
常用高阶函数详解:帮你处理数据的智能工具
1. filter():智能筛选器
作用:从数组中过滤出符合条件的元素,像过滤杂质一样
参数解释:每个元素传给回调函数,返回 true
则保留
代码示例(资料3)2:
const 数字组 = [1, 2, 3, 4, 5];
const 大于二 = 数字组.filter((当前数字) => 当前数字 > 2);
console.log(大于二); // [3, 4, 5]
比喻:像挑出水果篮中成熟的苹果
const 苹果 = ["青苹果", "烂苹果", "红苹果"];
const 好苹果 = 苹果.filter(苹果 => 苹果.includes("红")); // ["红苹果"]
2. map():流水线加工器
作用:将数组中每个元素转换处理后生成新数组,像工厂加工
参数解释:回调函数返回新值,组成新数组
代码示例(资料3)2:
const 原数组 = [1, 2, 3];
const 加倍数组 = 原数组.map(数字 => 数字 * 2);
console.log(加倍数组); // [2, 4, 6]
比喻:将蔬菜切成片
const 蔬菜 = ["黄瓜", "胡萝卜"];
const 切好的 = 蔬菜.map(菜 => 菜 + "片"); // ["黄瓜片", "胡萝卜片"]
3. every():全员安检员
作用:检查数组中所有元素是否都满足条件,否则返回 false
参数解释:全部返回 true
则整体为 true
代码示例(资料3)2:
const 成绩单 = [85, 90, 78];
const 全及格吗 = 成绩单.every(分数 => 分数 >= 60);
console.log(全及格吗); // true(都≥60分)
比喻:检查班级所有学生是否都交作业
const 作业状态 = [true, true, false];
console.log(作业状态.every(已交 => 已交)); // false(有人未交)
4. some():火眼侦察兵
作用:检查数组中是否至少有一个元素满足条件,遇到 true
就停止
参数解释:只要有一个返回 true
,整体即为 true
代码示例(资料3)2:
const 温度记录 = [22, 25, 18];
const 是否有高温 = 温度记录.some(温度 => 温度 > 29);
console.log(是否有高温); // false(没超过29度)
比喻:检查衣柜里是否有夏季衣服
const 衣服 = ["毛衣", "牛仔裤", "短袖"];
console.log(衣服.some(衣服 => 衣服 === "短袖")); // true
综合实战:订单处理
const 订单列表 = [
{ 商品: "手机", 价格: 2999 },
{ 商品: "耳机", 价格: 199 },
{ 商品: "充电宝", 价格: 150 }
];
// Step1:筛选高价商品(filter)
const 高价商品 = 订单列表.filter(订单 => 订单.价格 > 1000);
// [{ 手机: 2999 }]
// Step2:提取商品名称(map)
const 名称列表 = 订单列表.map(订单 => 订单.商品);
// ["手机", "耳机", "充电宝"]
// Step3:是否所有商品价格≥100(every)
const 全低价吗 = 订单列表.every(订单 => 订单.价格 < 100);
// false
// Step4:是否有商品价格超过2000(some)
const 有奢侈品吗 = 订单列表.some(订单 => 订单.价格 > 2000);
// true
注意事项:
- 回调函数参数顺序:
(当前元素, 索引, 原数组)
[10, 20, 30].map((元素, 索引) => 元素 + 索引); // 返回 [10+0, 20+1, 30+2] → [10, 21, 32]
- 不会修改原数组:返回新数组,原数据保持不变2
练习:用
filter
选出订单中价格在100-200元之间的商品。const 适中商品 = 订单列表.filter(订单 => 订单.价格 >= 100 && 订单.价格 <= 200);
reduce函数详解:数据汇总计算器
reduce的作用
reduce()
是数组处理中最灵活的高阶函数,可将数组元素累积计算成一个最终值。比如累加订单总价、连接字符串等。
核心概念:
- 遍历数组:逐个处理元素
- 累积结果:每一步的返回值作为下一次的初始值
基础语法
数组.reduce((累积器, 当前元素) => {
return 新累积值;
}, 初始值);
具体示例
1. 计算数组总和(初始累积器为0)
const 价格 = [100, 200, 300];
const 总价 = 价格.reduce((总和, 当前价格) => 总和 + 当前价格, 0);
// 总价 → 600
运算步骤:
- 初始值:0
- 第一次:0 + 100 → 100
- 第二次:100 + 200 → 300
- 第三次:300 + 300 → 600
2. 展平二维数组
const 二维数组 = [[1, 2], [3, 4], [5]];
const 展平后 = 二维数组.reduce((结果, 子数组) => 结果.concat(子数组), []);
// 展平后 → [1, 2, 3, 4, 5]
3. 统计词频
const 词语 = ["苹果", "香蕉", "苹果"];
const 统计 = 词语.reduce((词表, 词) => {
词表[词] = (词表[词] || 0) + 1;
return 词表;
}, {});
// 统计 → {苹果:2, 香蕉:1}
注意事项
必须提供初始值的情况:
- 数组为空时避免报错
- 累积类型不同时(如对象、数组)
示例:不提供初始值的陷阱
[1, 2, 3].reduce((sum, num) => sum + num);
// sum第一次是1,结果为6(可能预期不符时需显式初始)
综合实战:DOM内容合并(模拟参考中的文档碎片操作)
若需合并多个节点的文本:
const 节点列表 = document.querySelectorAll(".text-node");
const 合并文本 = Array.from(节点列表).reduce(
(文本, 节点) => 文本 + 节点.textContent,
""
);
总结
reduce
如同数学中的Σ符号,将每一步计算累积成结果。灵活用于求和、统计、转换等场景。
总结与练习
- 箭头函数:短小精悍,但小心
this
陷阱。 - 高阶函数:灵活处理数组,如工厂流水线。
练习:用
map
将所有菜品名称转为大写。const 大写菜单 = 订单.map(item => item.菜品.toUpperCase());
目录:总目录
上篇文章:红宝书第七讲:this绑定与强制类型转换详解(小白指南)
下篇文章:红宝书第九讲:JavaScript对象创建与属性描述符详解
高阶函数filter、map的具体用法示例,《JavaScript高级程序设计(第5版)》 第6章 ↩︎
高阶函数 filter、map、every、some 的具体用法示例,详见《JavaScript高级程序设计(第5版)》 中的 Array 相关章节 ↩︎ ↩︎ ↩︎ ↩︎ ↩︎