1.1 forEach 遍历
forEach 就是把数组里的每个元素都过一遍,对每个元素执行你给的函数。
它是 for 循环的"升级版",写法更简洁。
基本语法:
数组.forEach(function(当前元素, 当前索引, 原数组) {
// 对每个元素执行的操作
});
回调函数参数说明:
| 参数 | 含义 | 可选? |
|---|---|---|
当前元素 |
正在处理的那个元素 | 否 |
当前索引 |
元素的下标 | 是 |
原数组 |
forEach 所在的数组本身 | 是 |
演示代码:
1 // 模拟博客文章列表 2 let posts = [ 3 { title: 'JavaScript入门', author: '小明' }, 4 { title: 'CSS布局技巧', author: '小红' }, 5 { title: 'React教程', author: '小明' } 6 ]; 7 8 // forEach 遍历每个元素 9 posts.forEach(function(post, index) { 10 console.log(`${index + 1}. ${post.title} — 作者:${post.author}`); 11 }); 12 13 // 用箭头函数更简洁 14 posts.forEach((post, index) => { 15 console.log(`第${index + 1}篇:${post.title}`); 16 }); 17 18 // forEach 没有返回值 19 let result = posts.forEach(post => post.title); 20 console.log(result); // undefined
⚠️ 新手易错:
forEach 没有返回值,不能用 let arr = arr.forEach(...) 来接收结果。它只是"过一遍",不做变换。想变换用 map。
🎮 点击运行:
点击按钮运行代码,查看输出...
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>forEach 示例</title>
6</head>
7<body>
8 <h1>forEach 遍历</h1>
9 <script>
10 let posts = [
11 { title: 'JavaScript入门', author: '小明' },
12 { title: 'CSS布局技巧', author: '小红' },
13 { title: 'React教程', author: '小明' }
14 ];
15
16 posts.forEach(function(post, index) {
17 console.log(`${index + 1}. ${post.title} — 作者:${post.author}`);
18 });
19
20 posts.forEach((post, index) => {
21 console.log(`第${index + 1}篇:${post.title}`);
22 });
23
24 let result = posts.forEach(post => post.title);
25 console.log(result); // undefined
26 </script>
27</body>
28</html>
1.2 map 映射
map 是把数组里的每个元素都变一下,返回一个全新的数组,长度和原数组一样。
好比你有一篮子水果 [苹果, 香蕉, 橘子],map 就是给每个水果贴个标签,变成 [标签苹果, 标签香蕉, 标签橘子]。
基本语法:
let 新数组 = 数组.map(function(当前元素, 当前索引) {
return 变换后的值;
});
运行结果:
| 操作 | 原数组 | 新数组 |
|---|---|---|
| 提取标题 | [{}, {}, {}] |
['标题1', '标题2', '标题3'] |
| 添加字段 | [{views:1200}, ...] |
[{views:1200, isPopular:true}, ...] |
演示代码:
1 // 模拟博客文章列表 2 let posts = [ 3 { title: 'JavaScript入门', views: 1200 }, 4 { title: 'CSS布局技巧', views: 850 }, 5 { title: 'React教程', views: 3200 }, 6 { title: 'HTML语义化', views: 650 } 7 ]; 8 9 // map 提取所有标题 10 let titles = posts.map(post => post.title); 11 console.log(titles); 12 13 // map 变换格式:加上"次浏览" 14 let summaries = posts.map(post => 15 `${post.title}(${post.views}次浏览)` 16 ); 17 console.log(summaries); 18 19 // map 生成新对象(添加新字段) 20 let enriched = posts.map(post => ({ 21 ...post, 22 isPopular: post.views > 1000 23 })); 24 console.log(enriched);
⚠️ 新手易错:
map 里必须 return 一个值。如果忘了 return,新数组里每个元素都是 undefined。箭头函数简写 post => post.title 会自动 return,但写了 {} 就必须手动 return。
🎮 点击运行:
点击按钮运行代码,查看输出...
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>map 示例</title>
6</head>
7<body>
8 <h1>map 映射</h1>
9 <script>
10 let posts = [
11 { title: 'JavaScript入门', views: 1200 },
12 { title: 'CSS布局技巧', views: 850 },
13 { title: 'React教程', views: 3200 },
14 { title: 'HTML语义化', views: 650 }
15 ];
16
17 let titles = posts.map(post => post.title);
18 console.log(titles);
19
20 let summaries = posts.map(post =>
21 `${post.title}(${post.views}次浏览)`
22 );
23 console.log(summaries);
24
25 let enriched = posts.map(post => ({
26 ...post,
27 isPopular: post.views > 1000
28 }));
29 console.log(enriched);
30
31 console.log(posts); // 原数组不变
32 </script>
33</body>
34</html>
1.3 filter 过滤
filter 是从数组里挑出符合条件的元素,返回一个新数组,长度可能比原数组短。
好比你有一篮子水果,filter 就是只留下红苹果,其他的都不要。
基本语法:
let 新数组 = 数组.filter(function(当前元素) {
return 条件; // true 保留,false 丢弃
});
filter 工作原理:
| 元素 | 条件 views > 1000 | 结果 |
|---|---|---|
{views: 1200} |
1200 > 1000 → true | ✅ 保留 |
{views: 850} |
850 > 1000 → false | ❌ 丢弃 |
{views: 3200} |
3200 > 1000 → true | ✅ 保留 |
{views: 650} |
650 > 1000 → false | ❌ 丢弃 |
演示代码:
1 let posts = [ 2 { title: 'JavaScript入门', views: 1200, draft: false }, 3 { title: 'CSS布局技巧', views: 850, draft: false }, 4 { title: 'React教程', views: 3200, draft: true }, 5 { title: 'HTML语义化', views: 650, draft: false }, 6 { title: '未完成的文章', views: 0, draft: true } 7 ]; 8 9 // 过滤已发布的文章 10 let published = posts.filter(post => post.draft === false); 11 console.log(published); 12 13 // 过滤浏览量超过1000的文章 14 let popular = posts.filter(post => post.views > 1000); 15 console.log(popular); 16 17 // 链式调用:先过滤再提取标题 18 let popularTitles = posts 19 .filter(post => post.views > 1000) 20 .map(post => post.title); 21 console.log(popularTitles);
💡 提示:
filter 和 map 经常链式调用:先 filter 筛选,再 map 变换。这是数据处理中最常见的组合。
🎮 点击运行:
点击按钮运行代码,查看输出...
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>filter 示例</title>
6</head>
7<body>
8 <h1>filter 过滤</h1>
9 <script>
10 let posts = [
11 { title: 'JavaScript入门', views: 1200, draft: false },
12 { title: 'CSS布局技巧', views: 850, draft: false },
13 { title: 'React教程', views: 3200, draft: true },
14 { title: 'HTML语义化', views: 650, draft: false },
15 { title: '未完成的文章', views: 0, draft: true }
16 ];
17
18 let published = posts.filter(post => post.draft === false);
19 console.log(published);
20
21 let popular = posts.filter(post => post.views > 1000);
22 console.log(popular);
23
24 let beginnerPosts = posts.filter(post => post.title.includes('入门'));
25 console.log(beginnerPosts);
26
27 let popularTitles = posts
28 .filter(post => post.views > 1000)
29 .map(post => post.title);
30 console.log(popularTitles);
31 </script>
32</body>
33</html>
1.4 find 查找
find 是从数组里找到第一个符合条件的元素,只返回一个元素(不是数组)。找不到返回 undefined。
和 filter 的区别:filter 返回所有匹配的(数组),find 只返回第一个匹配的(单个元素)。
基本语法:
let 结果 = 数组.find(function(当前元素) {
return 条件;
});
filter vs find 对比:
| 特性 | filter |
find |
|---|---|---|
| 返回值 | 数组(所有匹配的) | 单个元素(第一个匹配的) |
| 找不到 | 返回空数组 [] |
返回 undefined |
| 使用场景 | 我要所有符合条件的 | 我只要第一个 |
演示代码:
1 let posts = [ 2 { id: 1, title: 'JavaScript入门', views: 1200 }, 3 { id: 2, title: 'CSS布局技巧', views: 850 }, 4 { id: 3, title: 'React教程', views: 3200 }, 5 { id: 4, title: 'HTML语义化', views: 650 } 6 ]; 7 8 // find:找到 id 为 3 的文章 9 let post = posts.find(post => post.id === 3); 10 console.log(post); 11 12 // find:找不到返回 undefined 13 let notFound = posts.find(post => post.id === 99); 14 console.log(notFound); // undefined 15 16 // filter vs find 17 let filtered = posts.filter(p => p.views > 1000); 18 let found = posts.find(p => p.views > 1000); 19 console.log('filter:', filtered); // 数组 20 console.log('find:', found); // 单个对象
⚠️ 新手易错:
find 返回的是元素本身(引用),不是副本。修改 find 的结果会直接影响原数组。
🎮 点击运行:
点击按钮运行代码,查看输出...
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>find 示例</title>
6</head>
7<body>
8 <h1>find 查找</h1>
9 <script>
10 let posts = [
11 { id: 1, title: 'JavaScript入门', views: 1200 },
12 { id: 2, title: 'CSS布局技巧', views: 850 },
13 { id: 3, title: 'React教程', views: 3200 },
14 { id: 4, title: 'HTML语义化', views: 650 }
15 ];
16
17 let post = posts.find(post => post.id === 3);
18 console.log(post);
19
20 let popular = posts.find(post => post.views > 2000);
21 console.log(popular);
22
23 let notFound = posts.find(post => post.id === 99);
24 console.log(notFound); // undefined
25
26 let filtered = posts.filter(p => p.views > 1000);
27 let found = posts.find(p => p.views > 1000);
28 console.log(filtered); // 数组
29 console.log(found); // 单个对象
30 </script>
31</body>
32</html>
1.5 reduce 归纳
reduce 是最强大的数组方法——把数组里的所有元素归拢成一个值(数字、字符串、对象、数组都行)。
它可以替代 map、filter、forEach 的所有功能(虽然不一定需要这么做)。
基本语法:
let 结果 = 数组.reduce(function(累加器, 当前元素) {
return 新的累加器;
}, 初始值);
回调函数参数说明:
| 参数 | 含义 |
|---|---|
累加器 |
每轮计算的结果,传递给下一轮 |
当前元素 |
正在处理的元素 |
当前索引 |
正在处理的元素的下标(可选) |
原数组 |
reduce 所在的数组(可选) |
reduce 执行过程(以 [10,20,30,40,50] 求和为例):
| 轮次 | 累加器 (acc) | 当前元素 (cur) | 返回值 |
|---|---|---|---|
| 1 | 0(初始值) | 10 | 10 |
| 2 | 10 | 20 | 30 |
| 3 | 30 | 30 | 60 |
| 4 | 60 | 40 | 100 |
| 5 | 100 | 50 | 150 |
演示代码:
1 // ========== 求和(最经典用法) ========== 2 let numbers = [10, 20, 30, 40, 50]; 3 let sum = numbers.reduce((acc, cur) => acc + cur, 0); 4 console.log('总和:' + sum); // 150 5 6 // ========== 统计博客数据 ========== 7 let posts = [ 8 { title: 'JavaScript入门', views: 1200, category: 'JS' }, 9 { title: 'CSS布局技巧', views: 850, category: 'CSS' }, 10 { title: 'React教程', views: 3200, category: 'React' }, 11 { title: 'HTML语义化', views: 650, category: 'HTML' }, 12 { title: 'Vue入门', views: 1800, category: 'Vue' } 13 ]; 14 15 // 用 reduce 统计总浏览量 16 let totalViews = posts.reduce((sum, post) => sum + post.views, 0); 17 console.log('总浏览量:' + totalViews); // 7700 18 19 // 用 reduce 按分类分组 20 let grouped = posts.reduce((groups, post) => { 21 let cat = post.category; 22 if (!groups[cat]) groups[cat] = []; 23 groups[cat].push(post.title); 24 return groups; 25 }, {}); 26 console.log(grouped);
⚠️ 新手易错:
⚠️ 新手易错:
reduce 的初始值(第二个参数)不要省略。空数组不传初始值会报错 TypeError: Reduce of empty array with no initial value。传初始值更安全。⚠️ 新手易错:
reduce 的回调函数必须返回累加器。忘了 return,累加器会变成 undefined。
🎮 点击运行:
点击按钮运行代码,查看输出...
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>reduce 示例</title>
6</head>
7<body>
8 <h1>reduce 归纳</h1>
9 <script>
10 let numbers = [10, 20, 30, 40, 50];
11 let sum = numbers.reduce((acc, cur) => acc + cur, 0);
12 console.log('总和:' + sum);
13
14 let posts = [
15 { title: 'JavaScript入门', views: 1200, category: 'JS' },
16 { title: 'CSS布局技巧', views: 850, category: 'CSS' },
17 { title: 'React教程', views: 3200, category: 'React' },
18 { title: 'HTML语义化', views: 650, category: 'HTML' },
19 { title: 'Vue入门', views: 1800, category: 'Vue' }
20 ];
21
22 let totalViews = posts.reduce((sum, post) => sum + post.views, 0);
23 console.log('总浏览量:' + totalViews);
24
25 let grouped = posts.reduce((groups, post) => {
26 let cat = post.category;
27 if (!groups[cat]) groups[cat] = [];
28 groups[cat].push(post.title);
29 return groups;
30 }, {});
31 console.log(grouped);
32
33 let mostViewed = posts.reduce((max, post) => {
34 return post.views > max.views ? post : max;
35 }, posts[0]);
36 console.log('最多浏览:' + mostViewed.title);
37 </script>
38</body>
39</html>
1.6 some 和 every
some 检查数组里是否至少有一个元素符合条件;every 检查是否所有元素都符合条件。返回布尔值。
some vs every 对比:
| 方法 | 逻辑 | 类比 | 找到第一个就 |
|---|---|---|---|
some |
有一个满足就 true | 班里有没有及格的同学? | 停止,返回 true |
every |
全部满足才 true | 班里是不是都及格了? | 不满足就停止,返回 false |
演示代码:
1 let posts = [ 2 { title: 'JavaScript入门', views: 1200, published: true }, 3 { title: 'CSS布局技巧', views: 850, published: true }, 4 { title: 'React教程', views: 3200, published: false }, 5 { title: 'HTML语义化', views: 650, published: true } 6 ]; 7 8 // ========== some ========== 9 let hasViral = posts.some(post => post.views > 3000); 10 console.log('有爆款文章?' + hasViral); // true 11 12 let hasSuperPopular = posts.some(post => post.views > 10000); 13 console.log('有超热门?' + hasSuperPopular); // false 14 15 // ========== every ========== 16 let allPublished = posts.every(post => post.published === true); 17 console.log('全部已发布?' + allPublished); // false 18 19 let allAbove500 = posts.every(post => post.views > 500); 20 console.log('全部超过500?' + allAbove500); // true
🎮 点击运行:
点击按钮运行代码,查看输出...
所有数组高阶方法速查表:
| 方法 | 作用 | 返回值 | 改变原数组? |
|---|---|---|---|
forEach |
遍历执行 | undefined |
否 |
map |
映射变换 | 新数组 | 否 |
filter |
过滤筛选 | 新数组 | 否 |
find |
查找第一个 | 单个元素 | 否 |
reduce |
归纳为一个值 | 任意值 | 否 |
some |
至少一个满足? | 布尔值 | 否 |
every |
全部满足? | 布尔值 | 否 |
本章复盘——核心要点:
| 方法 | 一句话说明 | 典型场景 |
|---|---|---|
| forEach | 遍历每个元素,不返回值 | 打印日志、DOM操作 |
| map | 每个元素变一下,返回新数组 | 提取字段、格式转换 |
| filter | 挑出符合条件的,返回新数组 | 筛选数据 |
| find | 找第一个符合条件的,返回单个 | 根据ID找数据 |
| reduce | 所有元素归拢成一个值 | 求和、分组、统计 |
| some | 至少有一个满足? | 检查是否存在 |
| every | 全部满足? | 表单验证 |
⚠️ 新手易错:这些方法都不会修改原数组。如果要更新原数组,用返回的新数组去覆盖:
posts = posts.filter(...)。
1<!DOCTYPE html>
2<html lang="zh-CN">
3<head>
4 <meta charset="UTF-8">
5 <title>some 和 every 示例</title>
6</head>
7<body>
8 <h1>some 和 every</h1>
9 <script>
10 let posts = [
11 { title: 'JavaScript入门', views: 1200, published: true },
12 { title: 'CSS布局技巧', views: 850, published: true },
13 { title: 'React教程', views: 3200, published: false },
14 { title: 'HTML语义化', views: 650, published: true }
15 ];
16
17 let hasViral = posts.some(post => post.views > 3000);
18 console.log('有爆款文章?' + hasViral);
19
20 let hasSuperPopular = posts.some(post => post.views > 10000);
21 console.log('有超热门?' + hasSuperPopular);
22
23 let allPublished = posts.every(post => post.published === true);
24 console.log('全部已发布?' + allPublished);
25
26 let allAbove500 = posts.every(post => post.views > 500);
27 console.log('全部超过500?' + allAbove500);
28 </script>
29</body>
30</html>