1. 为什么我们需要这么多filter函数?
在日常开发中,数据过滤是最基础也最频繁的操作之一。我见过太多项目因为缺乏统一的过滤工具函数,导致每个开发者都自己写一套,最终代码库中散落着几十种不同风格的filter实现。这不仅造成维护困难,还容易引入潜在bug。
filter操作的本质是从数据集合中筛选出符合条件的元素。根据我的经验,一个完善的filter工具库应该覆盖以下场景:
- 基础值过滤(数字、字符串、布尔值)
- 对象属性过滤
- 数组多条件过滤
- 嵌套数据结构过滤
- 特殊业务场景过滤(如权限、状态)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. JavaScript核心filter方法解析
2.1 原生Array.prototype.filter
这是JS中最基础的过滤方法,任何前端开发者都应该熟练掌握:
javascript复制const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(n => n % 2 === 0);
// [2, 4]
关键点:
- 不会修改原数组
- 回调函数需要返回布尔值
- 稀疏数组处理需特别注意
2.2 Vue3中的computed与filter
Vue3虽然移除了filter管道符语法,但我们可以用computed实现更强大的过滤逻辑:
javascript复制import { computed } from 'vue';
const filteredList = computed(() => {
return sourceList.value.filter(item => item.status === 'active');
});
相比Vue2的filter,这种方式的优势在于:
- 更好的TypeScript支持
- 更清晰的依赖追踪
- 性能优化空间更大
3. 实用filter工具函数大全
3.1 基础类型过滤
javascript复制// 过滤非空值
const filterTruthy = arr => arr.filter(Boolean);
// 过滤唯一值
const filterUnique = arr => arr.filter(
(item, index) => arr.indexOf(item) === index
);
// 数字范围过滤
const filterInRange = (arr, min, max) =>
arr.filter(n => n >= min && n <= max);
3.2 对象数组过滤
javascript复制// 按属性值过滤
const filterByProp = (arr, prop, value) =>
arr.filter(item => item[prop] === value);
// 多条件AND过滤
const filterMultiAnd = (arr, conditions) =>
arr.filter(item =>
Object.entries(conditions).every(([k, v]) => item[k] === v)
);
// 多条件OR过滤
const filterMultiOr = (arr, conditions) =>
arr.filter(item =>
Object.entries(conditions).some(([k, v]) => item[k] === v)
);
3.3 高级过滤技巧
javascript复制// 深度过滤(处理嵌套对象)
const deepFilter = (arr, predicate) => {
const deepFilterImpl = obj => {
if (Array.isArray(obj)) {
return obj.map(deepFilterImpl).filter(predicate);
}
if (typeof obj === 'object' && obj !== null) {
return Object.fromEntries(
Object.entries(obj)
.map(([k, v]) => [k, deepFilterImpl(v)])
.filter(([_, v]) => predicate(v))
);
}
return obj;
};
return arr.map(deepFilterImpl).filter(predicate);
};
// 异步过滤
async function asyncFilter(arr, predicate) {
const results = await Promise.all(arr.map(predicate));
return arr.filter((_, index) => results[index]);
}
4. 性能优化与边界情况处理
4.1 大数据量优化
当处理超过10万条数据时,常规filter方法可能造成性能问题。这时可以考虑:
- 使用Web Worker分流处理
- 分批处理(chunk)数据
- 使用更高效的数据结构(如Bloom Filter)
javascript复制// 分批处理示例
async function chunkFilter(arr, predicate, chunkSize = 1000) {
const result = [];
for (let i = 0; i < arr.length; i += chunkSize) {
const chunk = arr.slice(i, i + chunkSize);
result.push(...chunk.filter(predicate));
await new Promise(resolve => setTimeout(resolve, 0));
}
return result;
}
4.2 常见边界情况
- 稀疏数组处理:
javascript复制const sparse = [1, , , 4];
// 常规filter会跳过空位
sparse.filter(x => true); // [1, 4]
// 如果需要保留空位
const denseFilter = (arr, predicate) => {
const result = [];
for (let i = 0; i < arr.length; i++) {
result[i] = predicate(arr[i], i, arr) ? arr[i] : undefined;
}
return result;
};
- 类数组对象处理:
javascript复制function filterArrayLike(arrayLike, predicate) {
return Array.prototype.filter.call(arrayLike, predicate);
}
- 内存泄漏预防:
javascript复制// 避免在filter回调中保留外部引用
const createFilter = () => {
const heavyObject = new Array(1e6).fill(0);
return arr => arr.filter(item => {
// 错误:闭包保留了heavyObject
// return item === heavyObject[0];
// 正确:不保留外部引用
return item === 0;
});
};
5. 框架与生态中的filter实践
5.1 Vue3组合式API中的过滤
javascript复制import { ref, computed } from 'vue';
export function useListFilter() {
const sourceList = ref([]);
const searchTerm = ref('');
const filteredList = computed(() => {
const term = searchTerm.value.toLowerCase();
return sourceList.value.filter(item =>
item.name.toLowerCase().includes(term)
);
});
return { sourceList, searchTerm, filteredList };
}
5.2 React中的记忆化过滤
javascript复制import { useMemo } from 'react';
function FilteredList({ items, searchTerm }) {
const filteredItems = useMemo(() => {
return items.filter(item =>
item.name.includes(searchTerm)
);
}, [items, searchTerm]);
return <ul>{filteredItems.map(/* ... */)}</ul>;
}
5.3 Lodash与Ramda对比
javascript复制// Lodash方式
_.filter(users, { active: true });
// Ramda方式
R.filter(R.propEq('active', true), users);
关键区别:
- Lodash:更接近原生JS风格
- Ramda:更函数式,支持柯里化
- 性能:原生 > Lodash > Ramda(在小数据量下差异不明显)
6. 单元测试与类型安全
6.1 测试filter函数
javascript复制describe('filter functions', () => {
test('filterByProp should work', () => {
const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false }
];
expect(filterByProp(users, 'active', true)).toEqual([
{ id: 1, name: 'Alice', active: true }
]);
});
});
6.2 TypeScript类型定义
typescript复制// 基础filter类型
type FilterPredicate<T> = (value: T, index: number, array: T[]) => boolean;
// 带属性的filter
function filterByProp<T, K extends keyof T>(
arr: T[],
prop: K,
value: T[K]
): T[] {
return arr.filter(item => item[prop] === value);
}
// 使用示例
interface User {
id: number;
name: string;
active: boolean;
}
const users: User[] = [/* ... */];
const activeUsers = filterByProp(users, 'active', true); // 类型推断正确
7. 业务场景实战案例
7.1 电商商品过滤
javascript复制function filterProducts(products, filters) {
return products.filter(product => {
// 价格区间
if (filters.minPrice && product.price < filters.minPrice) return false;
if (filters.maxPrice && product.price > filters.maxPrice) return false;
// 多选品牌
if (filters.brands?.length && !filters.brands.includes(product.brand)) {
return false;
}
// 搜索关键词
if (filters.search) {
const searchFields = ['name', 'description', 'sku'];
const searchLower = filters.search.toLowerCase();
if (!searchFields.some(field =>
String(product[field]).toLowerCase().includes(searchLower)
)) {
return false;
}
}
return true;
});
}
7.2 表格数据过滤
javascript复制function filterTableData(data, columns, filters) {
return data.filter(row => {
return columns.every(column => {
const filterFn = filters[column.key];
if (!filterFn) return true;
return filterFn(row[column.key]);
});
});
}
// 使用示例
const filteredData = filterTableData(
tableData,
[
{ key: 'name', title: 'Name' },
{ key: 'age', title: 'Age' }
],
{
name: value => value.includes('John'),
age: value => value > 18
}
);
8. 函数式编程进阶
8.1 组合filter函数
javascript复制const composeFilters = (...filters) => arr =>
filters.reduce((result, filterFn) => filterFn(result), arr);
// 使用示例
const filterActive = arr => arr.filter(u => u.active);
const filterAdults = arr => arr.filter(u => u.age >= 18);
const filterActiveAdults = composeFilters(filterActive, filterAdults);
8.2 惰性求值实现
javascript复制function* lazyFilter(iterable, predicate) {
for (const item of iterable) {
if (predicate(item)) {
yield item;
}
}
}
// 使用示例
const bigArray = new Array(1e6).fill(0).map((_, i) => i);
const filtered = lazyFilter(bigArray, x => x % 2 === 0);
// 只有在实际消费时才会执行过滤
for (const num of filtered) {
if (num > 10) break;
console.log(num);
}
9. 特殊场景处理
9.1 日期范围过滤
javascript复制function filterByDateRange(items, startDate, endDate, dateField = 'date') {
const start = new Date(startDate).getTime();
const end = new Date(endDate).getTime();
return items.filter(item => {
const itemDate = new Date(item[dateField]).getTime();
return itemDate >= start && itemDate <= end;
});
}
9.2 多语言文本过滤
javascript复制function filterByI18nText(items, lang, searchText, textField = 'text') {
return items.filter(item => {
const textObj = item[textField];
const text = textObj[lang] || textObj.default || '';
return text.toLowerCase().includes(searchText.toLowerCase());
});
}
10. 调试与性能分析
10.1 调试filter回调
javascript复制function debugFilter(arr, predicate) {
return arr.filter((item, index) => {
try {
const result = predicate(item, index, arr);
console.log(`[${index}]:`, item, '=>', result);
return result;
} catch (error) {
console.error(`Filter error at index ${index}:`, error);
return false;
}
});
}
10.2 性能测试工具
javascript复制function testFilterPerformance(filterFn, dataSize = 1e5, iterations = 100) {
const data = new Array(dataSize)
.fill(0)
.map((_, i) => ({ id: i, value: Math.random() }));
const start = performance.now();
for (let i = 0; i < iterations; i++) {
filterFn(data, item => item.value > 0.5);
}
const duration = performance.now() - start;
return {
dataSize,
iterations,
totalTime: duration,
avgTime: duration / iterations
};
}
11. 安全注意事项
11.1 防止原型污染
javascript复制function safeFilterByProp(arr, prop, value) {
// 防止通过__proto__等特殊属性污染原型
if (prop === '__proto__' || prop === 'constructor') {
return [];
}
return arr.filter(item => {
// 使用Object.prototype.hasOwnProperty.call防止覆盖
return Object.prototype.hasOwnProperty.call(item, prop) &&
item[prop] === value;
});
}
11.2 XSS防护
javascript复制function safeSearchFilter(arr, searchField, searchTerm) {
// 简单的XSS防护
const sanitize = str => str.replace(/</g, '<').replace(/>/g, '>');
const safeTerm = sanitize(searchTerm);
return arr.filter(item => {
const fieldValue = String(item[searchField]);
return sanitize(fieldValue).includes(safeTerm);
});
}
12. 现代JavaScript特性应用
12.1 使用Optional Chaining
javascript复制function filterNestedProps(arr, path, value) {
return arr.filter(item => {
// 使用可选链安全访问嵌套属性
const propValue = path.split('.').reduce(
(obj, key) => obj?.[key],
item
);
return propValue === value;
});
}
12.2 使用Private Fields
javascript复制class FilterProcessor {
#defaultPredicate = item => true;
constructor(predicate) {
if (predicate) {
this.#defaultPredicate = predicate;
}
}
filter(arr) {
return arr.filter(this.#defaultPredicate);
}
setPredicate(predicate) {
this.#defaultPredicate = predicate;
}
}
13. Web Worker并行过滤
javascript复制// worker.js
self.onmessage = function(e) {
const { data, predicate } = e.data;
const result = data.filter(predicate);
self.postMessage(result);
};
// 主线程
async function parallelFilter(arr, predicate, workerCount = 4) {
const chunkSize = Math.ceil(arr.length / workerCount);
const workers = [];
for (let i = 0; i < workerCount; i++) {
const worker = new Worker('worker.js');
const chunk = arr.slice(i * chunkSize, (i + 1) * chunkSize);
workers.push(new Promise(resolve => {
worker.onmessage = e => {
resolve(e.data);
worker.terminate();
};
worker.postMessage({ data: chunk, predicate });
}));
}
const results = await Promise.all(workers);
return results.flat();
}
14. 可视化过滤过程
javascript复制function visualizeFilter(arr, predicate, container) {
const list = document.createElement('ul');
arr.forEach((item, index) => {
const li = document.createElement('li');
li.textContent = JSON.stringify(item);
li.style.opacity = '0.5';
if (predicate(item, index, arr)) {
li.style.opacity = '1';
li.style.fontWeight = 'bold';
}
list.appendChild(li);
});
container.innerHTML = '';
container.appendChild(list);
}
15. 服务端过滤实践
15.1 Express中间件实现
javascript复制function createFilterMiddleware(filterFn) {
return (req, res, next) => {
const originalJson = res.json;
res.json = function(data) {
if (Array.isArray(data)) {
data = filterFn(data, req.query);
}
originalJson.call(this, data);
};
next();
};
}
// 使用示例
app.get('/api/users',
createFilterMiddleware((users, query) => {
return users.filter(user => {
if (query.active && user.active !== (query.active === 'true')) {
return false;
}
if (query.search && !user.name.includes(query.search)) {
return false;
}
return true;
});
}),
(req, res) => {
// 返回所有用户,但会被中间件过滤
res.json(getAllUsers());
}
);
15.2 数据库层面过滤
javascript复制// MongoDB示例
async function filterUsers(criteria) {
const query = {};
if (criteria.active) {
query.active = criteria.active === 'true';
}
if (criteria.search) {
query.$or = [
{ name: new RegExp(criteria.search, 'i') },
{ email: new RegExp(criteria.search, 'i') }
];
}
return await User.find(query);
}
16. 移动端优化策略
16.1 虚拟列表过滤
javascript复制function createVirtualFilter(scroller, items, renderItem) {
let filteredItems = [...items];
let predicate = () => true;
const update = () => {
filteredItems = items.filter(predicate);
scroller.update(filteredItems);
};
return {
setFilter(newPredicate) {
predicate = newPredicate;
update();
},
getVisibleItems() {
return filteredItems.slice(
scroller.startIndex,
scroller.endIndex + 1
).map(renderItem);
}
};
}
16.2 节流过滤
javascript复制function createThrottledFilter(filterFn, delay = 300) {
let timeout;
let lastArgs;
return function(...args) {
lastArgs = args;
if (!timeout) {
timeout = setTimeout(() => {
filterFn.apply(this, lastArgs);
timeout = null;
}, delay);
}
};
}
17. 状态管理集成
17.1 Redux选择器
javascript复制// selectors.js
export const getFilteredUsers = createSelector(
[state => state.users, state => state.filters],
(users, filters) => {
return users.filter(user => {
// 应用所有过滤条件
return Object.entries(filters).every(([key, value]) => {
if (value === null || value === undefined) return true;
return user[key] === value;
});
});
}
);
17.2 Pinia实现
javascript复制// useUserStore.js
export const useUserStore = defineStore('users', {
state: () => ({
users: [],
searchTerm: ''
}),
getters: {
filteredUsers(state) {
const term = state.searchTerm.toLowerCase();
return state.users.filter(user =>
user.name.toLowerCase().includes(term)
);
}
}
});
18. 测试驱动开发示例
18.1 先写测试
javascript复制describe('filterByDateRange', () => {
const items = [
{ date: '2023-01-01' },
{ date: '2023-02-15' },
{ date: '2023-03-20' }
];
it('should filter items within date range', () => {
const result = filterByDateRange(
items,
'2023-02-01',
'2023-02-28'
);
expect(result).toEqual([{ date: '2023-02-15' }]);
});
it('should handle invalid dates', () => {
const result = filterByDateRange(
items,
'invalid',
'2023-02-28'
);
expect(result).toEqual([]);
});
});
18.2 实现函数
javascript复制function filterByDateRange(items, start, end, dateField = 'date') {
const startDate = new Date(start);
const endDate = new Date(end);
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
return [];
}
return items.filter(item => {
const itemDate = new Date(item[dateField]);
return itemDate >= startDate && itemDate <= endDate;
});
}
19. 算法复杂度分析
19.1 时间复杂度
- 基础filter:O(n)
- 嵌套filter:O(n*m)(需避免)
- 多条件filter:通常O(n),但条件复杂时可能更高
优化建议:
- 对大数据集先进行索引
- 使用Map或Set进行快速查找
- 对排序数据使用二分查找
19.2 空间复杂度
- 基础filter:O(n)(新数组)
- 原地过滤:可以优化到O(1)(但会修改原数组)
javascript复制// 原地过滤实现
function filterInPlace(arr, predicate) {
let i = 0, j = 0;
while (i < arr.length) {
if (predicate(arr[i], i, arr)) {
arr[j++] = arr[i];
}
i++;
}
arr.length = j;
return arr;
}
20. 函数式编程库集成
20.1 Ramda示例
javascript复制import R from 'ramda';
const filterActive = R.filter(R.propEq('active', true));
const filterAdults = R.filter(user => user.age >= 18);
// 组合filter
const filterActiveAdults = R.compose(filterActive, filterAdults);
// 条件过滤
const filterByCondition = R.curry((condition, items) =>
R.filter(R.where(condition), items)
);
20.2 Lodash/fp示例
javascript复制import _ from 'lodash/fp';
const filterActive = _.filter({ active: true });
const filterBySearch = term =>
_.filter(item => _.includes(term, item.name));
// 组合使用
const processUsers = _.pipe(
filterActive,
filterBySearch('John'),
_.take(10)
);
21. Web组件中的过滤
21.1 自定义元素实现
javascript复制class FilterableList extends HTMLElement {
constructor() {
super();
this._items = [];
this._filter = '';
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<input type="text" id="filter">
<ul id="list"></ul>
`;
this.shadowRoot.getElementById('filter')
.addEventListener('input', e => {
this.filter = e.target.value;
this.render();
});
}
set items(value) {
this._items = value;
this.render();
}
set filter(value) {
this._filter = value.toLowerCase();
this.render();
}
render() {
const filtered = this._items.filter(item =>
item.toLowerCase().includes(this._filter)
);
const list = this.shadowRoot.getElementById('list');
list.innerHTML = filtered
.map(item => `<li>${item}</li>`)
.join('');
}
}
customElements.define('filterable-list', FilterableList);
21.2 LitElement实现
javascript复制import { LitElement, html } from 'lit';
class FilterableList extends LitElement {
static properties = {
items: { type: Array },
filter: { type: String }
};
constructor() {
super();
this.items = [];
this.filter = '';
}
get filteredItems() {
return this.items.filter(item =>
item.toLowerCase().includes(this.filter.toLowerCase())
);
}
render() {
return html`
<input
.value=${this.filter}
@input=${e => this.filter = e.target.value}
>
<ul>
${this.filteredItems.map(item => html`<li>${item}</li>`)}
</ul>
`;
}
}
customElements.define('filterable-list', FilterableList);
22. Node.js流式过滤
22.1 Transform流实现
javascript复制const { Transform } = require('stream');
class FilterStream extends Transform {
constructor(predicate, options) {
super({ ...options, objectMode: true });
this.predicate = predicate;
}
_transform(chunk, encoding, callback) {
if (this.predicate(chunk)) {
this.push(chunk);
}
callback();
}
}
// 使用示例
fs.createReadStream('data.json')
.pipe(JSON.parseStream()) // 假设有这个转换流
.pipe(new FilterStream(item => item.active))
.pipe(process.stdout);
22.2 高性能文件过滤
javascript复制async function filterLargeFile(inputPath, outputPath, predicate) {
const readStream = fs.createReadStream(inputPath, { encoding: 'utf8' });
const writeStream = fs.createWriteStream(outputPath);
let buffer = '';
let lineCount = 0;
for await (const chunk of readStream) {
buffer += chunk;
const lines = buffer.split('\n');
buffer = lines.pop(); // 保留最后不完整的行
for (const line of lines) {
lineCount++;
try {
const item = JSON.parse(line);
if (predicate(item)) {
writeStream.write(line + '\n');
}
} catch (err) {
console.error(`Error parsing line ${lineCount}:`, err);
}
}
}
// 处理剩余内容
if (buffer) {
try {
const item = JSON.parse(buffer);
if (predicate(item)) {
writeStream.write(buffer);
}
} catch (err) {
console.error(`Error parsing final line:`, err);
}
}
await new Promise(resolve => writeStream.end(resolve));
}
23. 机器学习数据预处理
23.1 数据集清洗
javascript复制function cleanDataset(data, options = {}) {
const {
minLength = 0,
maxLength = Infinity,
allowedChars = null,
filterFns = []
} = options;
return data.filter(item => {
// 长度过滤
if (item.length < minLength || item.length > maxLength) {
return false;
}
// 字符集过滤
if (allowedChars) {
const chars = new Set([...item]);
for (const char of chars) {
if (!allowedChars.includes(char)) {
return false;
}
}
}
// 自定义过滤
for (const filterFn of filterFns) {
if (!filterFn(item)) {
return false;
}
}
return true;
});
}
23.2 特征选择过滤
javascript复制function featureSelectionFilter(data, features) {
return data.map(item => {
const filtered = {};
for (const feature of features) {
if (feature in item) {
filtered[feature] = item[feature];
}
}
return filtered;
});
}
24. 可视化工具实现
24.1 实时过滤效果展示
javascript复制function createFilterVisualizer(data, container) {
const input = document.createElement('input');
const output = document.createElement('div');
container.append(input, output);
input.addEventListener('input', () => {
const term = input.value.toLowerCase();
const filtered = data.filter(item =>
JSON.stringify(item).toLowerCase().includes(term)
);
output.innerHTML = `
<div>显示 ${filtered.length} / ${data.length} 项</div>
<pre>${JSON.stringify(filtered.slice(0, 10), null, 2)}</pre>
${filtered.length > 10 ? '<div>...更多结果省略...</div>' : ''}
`;
});
}
24.2 过滤条件构建器
javascript复制class FilterBuilder {
constructor() {
this.conditions = [];
}
addCondition(field, operator, value) {
this.conditions.push({ field, operator, value });
return this;
}
buildFilterFn() {
return item => {
return this.conditions.every(({ field, operator, value }) => {
const itemValue = item[field];
switch (operator) {
case '=': return itemValue === value;
case '!=': return itemValue !== value;
case '>': return itemValue > value;
case '<': return itemValue < value;
case 'includes': return String(itemValue).includes(value);
default: return true;
}
});
};
}
}
// 使用示例
const builder = new FilterBuilder()
.addCondition('age', '>', 18)
.addCondition('name', 'includes', 'John');
const filterFn = builder.buildFilterFn();
const filteredUsers = users.filter(filterFn);
25. 国际化过滤支持
25.1 多语言文本过滤
javascript复制function createI18nFilter(locale) {
return function filterI18nText(items, searchTerm, textField = 'text') {
return items.filter(item => {
const textObj = item[textField];
const text = textObj[locale] || textObj.default || '';
return text.toLowerCase().includes(searchTerm.toLowerCase());
});
};
}
// 使用示例
const filterEn = createI18nFilter('en');
const filtered = filterEn(products, 'computer');
25.2 区域特定过滤
javascript复制function createLocaleAwareFilter(locale) {
return function filterByLocale(items) {
return items.filter(item => {
// 过滤掉不适合当前区域的内容
if (item.restrictedLocales?.includes(locale)) {
return false;
}
// 只显示当前区域可用的内容
if (item.availableLocales && !item.availableLocales.includes(locale)) {
return false;
}
return true;
});
};
}
26. 安全过滤模式
26.1 SQL注入防护
javascript复制function safeDatabaseFilter(query, filters) {
const where = [];
const params = [];
for (const [field, value] of Object.entries(filters)) {
// 简单的字段名验证
if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(field)) {
continue;
}
where.push(`${field} = ?`);
params.push(value);
}
if (where.length) {
query += ' WHERE ' + where.join(' AND ');
}
return { query, params };
}
26.2 XSS过滤
javascript复制function safeHTMLFilter(items, unsafeFields) {
return items.map(item => {
const safeItem = { ...item };
for (const field of unsafeFields) {
if (field in safeItem) {
safeItem[field] = safeItem[field]
.replace(/</g, '<')
.replace(/>/g, '>');
}
}
return safeItem;
});
}
27. 性能监控与优化
27.1 过滤性能统计
javascript复制function createMonitoredFilter(filterFn, name = 'filter') {
return function monitoredFilter(...args) {
const start = performance.now();
const result = filterFn.apply(this, args);
const duration = performance.now() - start;
console.log(`[${name}]`, {
inputSize: args[0]?.length || 0,
outputSize: result.length,
duration: duration.toFixed(2) + 'ms',
ratio: (result.length / (args[0]?.length || 1)).toFixed(2)
});
return result;
};
}
27.2 缓存过滤结果
javascript复制function createCachedFilter(filterFn, keyFn = JSON.stringify) {
const cache = new Map();
return function cachedFilter(...args) {
const key = keyFn(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = filterFn.apply(this, args);
cache.set(key, result);
return result;
};
}
28. 不可变数据过滤
28.1 Immutable.js示例
javascript复制import { List } from 'immutable';
function filterImmutable(data, predicate) {
return data.filter(predicate);
}
// 使用示例
const list = List([1, 2, 3, 4, 5]);
const filtered = filterImmutable(list, n => n % 2 === 0);
28.2 纯函数实现
javascript复制function pureFilter(arr, predicate) {
// 深度拷贝确保原数据不被修改
const copy = JSON.parse(JSON.stringify(arr));
return copy.filter(predicate);
}
29. 调试与错误处理
29.1 详细日志过滤
javascript复制function createLoggedFilter(filterFn, logger = console) {
return function loggedFilter(...args) {
logger.group('Filter operation');
logger.log('Input:', args[0]);
try {
const result = filterFn.apply(this, args);
logger.log('Output:', result);
logger.groupEnd();
return result;
} catch (error) {
logger.error('Filter error:', error);
logger.groupEnd();
throw error;
}
};
}
29.2 错误恢复过滤
javascript复制function createResilientFilter(filterFn, fallback = []) {
return function resilientFilter(...args) {
try {
return filterFn.apply(this, args);
} catch (error) {
console.error('Filter failed, using fallback:', error);
return fallback;
}
};
}
30. 组合过滤与映射
30.1 filterMap实现
javascript复制function filterMap(arr, filterFn, mapFn) {
return arr.reduce((result, item, index) => {
if (filterFn(item, index, arr)) {
result.push(mapFn(item, index, arr));
}
return result;
}, []);
}
// 使用示例
const numbers = [1, 2, 3, 4, 5];
const squaredEvens = filterMap(
numbers,
n => n % 2 === 0,
n => n * n
);
// [4, 16]
30.2 链式操作优化
javascript复制class ArrayProcessor {
constructor(arr) {
this._array = arr;
this._filters = [];
this._maps = [];
}
filter(predicate) {
this._filters.push(predicate);
return this;
}
map(mapper) {
this._maps.push(mapper);
return this;
}
execute() {
let result = [...this._array];
for (const filterFn of this._filters) {
result = result.filter(filterFn);
}
for (const mapFn of this._maps) {
result = result.map(mapFn);
}
return result;
}
}
// 使用示例
const processor = new ArrayProcessor([1, 2, 3, 4, 5])
