在日常前端开发中,我们几乎每天都在和数组、对象打交道。无论是处理接口返回的数据、做状态管理,还是渲染列表组件,熟练掌握 JavaScript 提供的这些原生遍历与操作方法,是写出高效、可读性强代码的关键。
今天,我将带你系统梳理 8 个最常用、最核心的数组与对象方法:forEach、every、some、filter、map、reduce、find/findIndex、以及 ES6 的 Object.keys/values/entries,并结合 React 实战场景,让你真正“学以致用”。
1. forEach:基础遍历,但有局限
定义
forEach 用于按升序为数组中每个有效值执行一次回调函数。
array.forEach(function(currentValue, index, arr), thisValue)
currentValue(必需):当前元素的值index(可选):当前元素索引arr(可选):原数组
注意事项
- 不能中途
break或continue,只能用return跳过本次回调。 - 永远返回
undefined,即使你在回调中return其他值。
const nums = [1, 2, 3];
const result = nums.forEach(n => console.log(n));
console.log(result); // undefined
适用场景:仅用于执行副作用(如打印、修改外部变量),不适合做数据转换或提前终止的逻辑。
2. every:全真才为真
定义
检测数组所有元素是否都满足条件,一旦发现不满足的元素,立即返回 false,不再继续遍历。
[12, 54, 18, 130, 44].every(x => x >= 10); // true
[12, 5, 8, 130, 44].every(x => x >= 10); // false
应用场景
- 表单校验:所有输入项是否都合法?
- 权限判断:用户是否拥有所有所需权限?
const permissions = ['read', 'write', 'delete'];
const userPerms = ['read', 'write', 'delete', 'admin'];
const hasAll = permissions.every(p => userPerms.includes(p));
console.log(hasAll); // true
短路优化:性能友好,一旦不满足立即退出。
3. some:一真即为真
定义
检测数组中是否有至少一个元素满足条件,一旦找到满足的元素,立即返回 true。
[2, 5, 8, 1, 4].some(x => x > 10); // false
[12, 5, 8, 1, 4].some(x => x > 10); // true
实战用途
- 搜索功能:是否存在包含关键词的条目?
- 状态判断:是否有未完成的任务?
const tasks = [
{ id: 1, done: false },
{ id: 2, done: true }
];
const hasPending = tasks.some(t => !t.done);
console.log(hasPending); // true
同样具备短路特性,效率高。
4. filter:筛选过滤,生成新数组
定义
返回一个新数组,包含所有通过测试函数的元素。不修改原数组。
const strings = ["apple", "", "banana", " ", "cherry", null];
const validStrings = strings.filter(s => s && s.trim());
// ['apple', 'banana', 'cherry']
React 中的经典用法:瀑布流布局
<div className={styles.column}>
{images
.filter((_, i) => i % 2 === 0) // 筛选偶数索引图片
.map(img => (
<ImageCard key={img.id} img={img} />
))
}
</div>
技巧:
filter + map组合拳,先筛选再渲染,逻辑清晰。
5. map:一对一映射,生成新数组
定义
对数组每个元素执行函数,返回新数组,长度与原数组一致。
const a = ['1', '2', '3'];
const result = a.map(value => value + '新元素');
// ['1新元素', '2新元素', '3新元素']
关键点
- 返回新数组,不改变原数组。
- 常用于 JSX 中渲染列表。
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
切记:React 中
map的key应使用稳定 ID,避免用index,防止列表更新时出现渲染 bug。
6. reduce:累计器,功能最强大
定义
对数组元素“累积”计算,最终返回一个值。常用于求和、扁平化、分组等。
示例 1:求数组总和
const sum = [1, 2, 3, 4, 5].reduce((acc, curr) => acc + curr, 0);
// 15
示例 2:数组扁平化
const arrays = [[1,2], [3,4], [5,6]];
const flat = arrays.reduce((acc, curr) => acc.concat(curr), []);
// [1,2,3,4,5,6]
示例 3:对象分组(如按状态分类任务)
const tasks = [
{ id: 1, status: 'active' },
{ id: 2, status: 'done' },
{ id: 3, status: 'active' }
];
const grouped = tasks.reduce((acc, task) => {
(acc[task.status] = acc[task.status] || []).push(task);
return acc;
}, {});
// { active: [...], done: [...] }
💥
reduce是函数式编程的灵魂,掌握它,你就掌握了数据变换的“上帝之手”。
7. find & findIndex:精准查找
find()
返回第一个满足条件的元素,否则返回 undefined。
[1, 4, -5, 10].find(n => n < 0); // -5
[1, 4, 10, NaN].find(n => Object.is(NaN, n)); // NaN
findIndex()
返回第一个满足条件的元素索引,否则返回 -1。
[1, 4, -5, 10].findIndex(n => n < 0); // 2
[1, 4, 0, 10].findIndex(n => n < 0); // -1
🆚 vs indexOf / includes
indexOf只能查严格相等的值,不能查对象或复杂条件。find支持自定义判断逻辑,更灵活。
const users = [{ id: 1, name: 'A' }, { id: 2, name: 'B' }];
const user = users.find(u => u.id === 2); // { id: 2, name: 'B' }
8. Object.keys() / values() / entries():对象遍历三剑客
ES6 提供了三个静态方法,用于遍历对象的键、值、键值对。
| 方法 | 返回 | 用途 |
|---|---|---|
Object.keys(obj) | 字符串数组 | 遍历属性名 |
Object.values(obj) | 值数组 | 遍历属性值 |
Object.entries(obj) | [key, value] 数组 | 遍历键值对 |
✅ 实战 1:渲染配置项标题(keys)
{Object.keys(settings).map(key => (
<li key={key}><strong>{key}</strong></li>
))}
✅ 实战 2:显示用户信息(values)
{Object.values(user).map((value, index) => (
<li key={index}>{value}</li>
))}
✅ 实战 3:渲染键值对表格(entries)
{Object.entries(userData).map(([key, value]) => (
<tr key={key}>
<td>{key}</td>
<td>{value}</td>
</tr>
))}
⚠️ 注意:
key推荐使用key本身(如对象 ID 或属性名),避免用index。- 大对象可配合
useMemo缓存结果,避免重复计算。- TypeScript 中注意
Object.entries()的类型推断。
📌 总结:一张表掌握核心差异
| 方法 | 返回值 | 是否改变原数组 | 是否短路 | 典型用途 |
|---|---|---|---|---|
forEach | undefined | 否 | ❌ | 执行副作用 |
every | boolean | 否 | ✅ | 全部满足? |
some | boolean | 否 | ✅ | 至少一个满足? |
filter | 新数组 | 否 | ❌ | 筛选元素 |
map | 新数组 | 否 | ❌ | 数据映射 |
reduce | 累积值 | 否 | ❌ | 汇总、分组、扁平化 |
find | 元素 or undefined | 否 | ✅ | 查找元素 |
findIndex | 索引 or -1 | 否 | ✅ | 查找索引 |
Object.keys | 字符串数组 | 否 | ❌ | 遍历键名 |
Object.values | 值数组 | 否 | ❌ | 遍历值 |
Object.entries | 键值对数组 | 否 | ❌ | 遍历键值对 |
写在最后
这 8 个方法是 JavaScript 数据处理的“瑞士军刀”。理解它们的差异和适用场景,能让你的代码更简洁、高效、函数式。
- 想遍历?用
forEach(副作用)或map(映射)。 - 想判断?用
every(全真)或some(一真)。 - 想筛选?用
filter。 - 想查找?用
find/findIndex。 - 想汇总?用
reduce。 - 想遍历对象?用
Object.keys/values/entries。
🔥 记住:能用这些函数式方法的,就不要写
for循环!
希望这篇文章能帮你彻底掌握这些核心方法。如果觉得有用,欢迎点赞、收藏、分享,也欢迎在评论区交流你的使用心得!