filter()
和 find()
都是 JavaScript 数组的高阶函数,用于搜索数组元素,但它们有几个关键区别:
1. 基本区别
特性 | filter() | find() |
---|---|---|
返回值 | 新数组(包含所有匹配元素) | 第一个匹配的元素(不是数组) |
空结果 | 返回空数组 [] | 返回 undefined |
用途 | 筛选多个符合条件的元素 | 查找第一个符合条件的元素 |
2. 代码示例对比
示例数组
const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false },
{ id: 3, name: 'Charlie', active: true },
{ id: 4, name: 'David', active: true }
];
使用 filter()
// 找出所有活跃用户
const activeUsers = users.filter(user => user.active);
console.log(activeUsers);
// 输出: [
// {id: 1, name: 'Alice', active: true},
// {id: 3, name: 'Charlie', active: true},
// {id: 4, name: 'David', active: true}
// ]
// 没有匹配项时
const noUsers = users.filter(user => user.age > 100);
console.log(noUsers); // 输出: []
使用 find()
// 查找第一个活跃用户
const firstActive = users.find(user => user.active);
console.log(firstActive);
// 输出: {id: 1, name: 'Alice', active: true}
// 没有匹配项时
const notFound = users.find(user => user.age > 100);
console.log(notFound); // 输出: undefined
3. 性能考虑
-
filter()
会遍历整个数组,即使已经找到所有符合条件的元素 -
find()
在找到第一个匹配项后立即停止遍历
// 性能测试
const bigArray = Array(1000000).fill(0).map((_, i) => i);
console.time('filter');
bigArray.filter(x => x === 500000); // 会检查所有元素
console.timeEnd('filter'); // 输出: filter: 5.22509765625 ms
console.time('find');
bigArray.find(x => x === 500000); // 找到后立即停止
console.timeEnd('find'); // 输出: find: 2.56298828125 ms
4. 链式调用差异
// filter可以继续链式调用
users
.filter(user => user.active)
.map(user => user.name)
.forEach(name => console.log(name));
// 输出:
// Alice
// Charlie
// David
// find不能链式调用数组方法(因为返回的是元素)
const userName = users.find(user => user.id === 2).name; // 直接访问属性
console.log(userName) //输出: Bob
5. 实际应用场景
适合使用 filter()
的情况:
-
需要获取所有匹配项
-
需要对结果集进行进一步操作(如再过滤、映射等)
-
需要确保总是返回数组(便于后续处理)
// 获取所有未完成的任务
const incompleteTasks = tasks.filter(task => !task.completed);
// 结合map使用
const activeUserNames = users
.filter(user => user.active)
.map(user => user.name);
适合使用 find()
的情况:
-
只需要第一个匹配项
-
检查数组中是否存在某个元素
-
查找特定ID的对象
// 查找特定用户
const user = users.find(user => user.id === 3);
console.log(user) //输出: { id: 3, name: 'Charlie', active: true },
// 检查是否存在管理员
const hasAdmin = users.find(user => user.role === 'admin') !== undefined;
console.log(hasAdmin ) //输出: false
6. 特殊注意事项
-
引用类型:两者都返回原始数组中的引用(不会创建副本)
const found = users.find(u => u.id === 1); found.name = 'Alex'; // 会修改原数组中的对象 console.log(users) //输出: [ // { id: 1, name: 'Alex', active: true }, // { id: 2, name: 'Bob', active: false }, // { id: 3, name: 'Charlie', active: true }, // { id: 4, name: 'David', active: true } // ]
-
稀疏数组:
const sparse = [1, , 3]; sparse.find(x => true); // 1 (跳过空位) sparse.filter(x => true); // [1, 3] (跳过空位)
-
this绑定:两者都接受第二个参数用于设置回调函数的
this
const checker = { threshold: 2, check(num) { return num > this.threshold; } }; [1, 2, 3].find(checker.check, checker); // 3
总结选择
-
需要 多个结果 → 用
filter()
-
只需要 第一个结果 → 用
find()
-
需要 性能优化(大数据集) → 优先考虑
find()
-
需要 确保数组返回值 → 用
filter()
-
进行 链式操作 → 用
filter()