1. 50个filter相关公共函数全景解析
在JavaScript生态中,filter作为数组处理的核心方法,几乎出现在每个前端项目的工具函数集里。我整理了50个高频使用的filter变体函数,这些函数经过Vue3、React等多个生产项目验证,覆盖数据清洗、表单验证、业务逻辑处理等典型场景。下面按功能分类详解这些实用工具:
1.1 基础过滤函数组
1.1.1 类型过滤三件套
javascript复制// 过滤非空值(undefined/null/'')
const filterEmpty = arr => arr.filter(Boolean)
// 过滤数字类型(包括字符串数字)
const filterNumbers = arr => arr.filter(v => !isNaN(parseFloat(v)))
// 过滤纯对象(排除数组/日期等)
const filterPlainObjects = arr => arr.filter(v =>
Object.prototype.toString.call(v) === '[object Object]'
)
1.1.2 条件过滤组合
javascript复制// 多条件AND过滤
const multiFilter = (arr, conditions) =>
arr.filter(item =>
Object.entries(conditions).every(([key, val]) => item[key] === val)
)
// 动态范围过滤(适合价格/日期区间)
const rangeFilter = (arr, key, [min, max]) =>
arr.filter(item => item[key] >= min && item[key] <= max)
实战经验:在Vue3的computed中使用这些过滤函数时,建议用memoization缓存结果,避免重复计算影响性能
1.2 业务场景专用函数
1.2.1 表单验证系列
javascript复制// 表单必填项验证
const validateRequired = formData =>
Object.entries(formData).filter(([_, val]) => !val).map(([key]) => key)
// 手机号格式过滤
const filterValidPhones = phones =>
phones.filter(v => /^1[3-9]\d{9}$/.test(v))
1.2.2 数据转换过滤
javascript复制// 对象数组转键值映射
const filterToMap = (arr, keyField, valueField) =>
Object.fromEntries(
arr.filter(item => item[keyField]).map(item => [item[keyField], item[valueField]])
)
// 树形数据扁平化过滤
const flattenTree = (tree, childKey = 'children') =>
tree.reduce((acc, node) => [
...acc,
node,
...(node[childKey] ? flattenTree(node[childKey]) : [])
], [])
1.3 高级组合函数
1.3.1 函数式编程组合
javascript复制// 过滤器管道(类似Vue的过滤器链)
const createFilterPipe = (...fns) => initialValue =>
fns.reduce((val, fn) => fn(val), initialValue)
// 条件分支过滤
const conditionalFilter = (arr, predicate, truthyFn, falsyFn) =>
arr.filter(item =>
predicate(item) ? truthyFn(item) : falsyFn(item)
)
1.3.2 性能优化方案
javascript复制// 分页过滤(大数据量场景)
const paginationFilter = (arr, page, size) =>
arr.filter((_, index) =>
index >= (page - 1) * size && index < page * size
)
// Web Worker异步过滤
const asyncFilter = (arr, predicate) =>
Promise.all(arr.map(predicate)).then(results =>
arr.filter((_, index) => results[index])
)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Vue3中的filter最佳实践
2.1 组合式API集成方案
在Vue3的setup语法中,推荐将filter函数封装为composable:
javascript复制// useFilters.js
export function useArrayFilters() {
const filterByKey = (arr, key) =>
computed(() => arr.value.filter(item => item[key]))
return { filterByKey }
}
// 组件内使用
import { useArrayFilters } from './useFilters'
const { filterByKey } = useArrayFilters()
const filteredList = filterByKey(rawList, 'active')
2.2 性能优化技巧
2.2.1 虚拟滚动集成
javascript复制// 配合vue-virtual-scroller使用
const getFilteredChunk = (source, filterFn, chunkSize = 50) =>
source.value
.filter(filterFn)
.slice(0, chunkSize)
2.2.2 防抖过滤实现
javascript复制import { debounce } from 'lodash-es'
const useDebouncedFilter = (source, filterFn, delay = 300) => {
const filtered = ref([])
const runFilter = debounce(() => {
filtered.value = source.value.filter(filterFn)
}, delay)
watch(source, runFilter, { immediate: true })
return filtered
}
3. 复杂场景解决方案
3.1 多维度过滤
3.1.1 交叉过滤实现
javascript复制const createFilterSystem = (filters) => {
const filterState = reactive({ ...filters })
const filteredData = computed(() => {
return sourceData.filter(item => {
return Object.entries(filterState).every(([key, condition]) => {
if (typeof condition === 'function') {
return condition(item[key])
}
return item[key] === condition
})
})
})
return { filterState, filteredData }
}
3.1.2 服务端过滤协议
javascript复制const buildServerFilterQuery = (localFilters) => {
const query = {}
Object.entries(localFilters).forEach(([key, value]) => {
if (Array.isArray(value)) {
query[`${key}_in`] = value.join(',')
} else if (value !== undefined) {
query[key] = value
}
})
return new URLSearchParams(query).toString()
}
3.2 特殊数据结构处理
3.2.1 二维数组处理
javascript复制const filter2DArray = (matrix, predicate) =>
matrix.map(row => row.filter(predicate)).filter(row => row.length)
// 使用案例:过滤矩阵中的负数
const positiveMatrix = filter2DArray([
[1, -2, 3],
[-4, 5, -6]
], n => n > 0)
// 结果: [[1, 3], [5]]
3.2.2 图数据过滤
javascript复制const filterGraphNodes = (graph, predicate) => {
const nodes = graph.nodes.filter(predicate)
const nodeIds = new Set(nodes.map(n => n.id))
return {
nodes,
edges: graph.edges.filter(edge =>
nodeIds.has(edge.source) && nodeIds.has(edge.target)
)
}
}
4. 调试与性能监控
4.1 过滤过程可视化
javascript复制const createLoggedFilter = (filterFn, label = 'Filter') =>
function loggedFilter(...args) {
console.time(label)
const before = args[0].length
const result = filterFn.apply(this, args)
console.log(`${label} reduced ${before} → ${result.length} items`)
console.timeEnd(label)
return result
}
4.2 性能基准测试
javascript复制const benchmarkFilter = (filterFn, testData, iterations = 1000) => {
const times = []
for (let i = 0; i < iterations; i++) {
const start = performance.now()
filterFn([...testData])
times.push(performance.now() - start)
}
return {
avg: times.reduce((a, b) => a + b, 0) / times.length,
p95: times.sort()[Math.floor(times.length * 0.95)]
}
}
5. 完整工具函数库实现
以下是可直接复用的filter工具类实现:
javascript复制class ArrayFilters {
static byRegex(arr, pattern, key) {
const regex = new RegExp(pattern)
return key
? arr.filter(item => regex.test(item[key]))
: arr.filter(item => regex.test(item))
}
static uniqueBy(arr, key) {
const seen = new Set()
return arr.filter(item => {
const val = item[key]
return seen.has(val) ? false : seen.add(val)
})
}
static chunkFilter(arr, chunkSize, filterFn) {
const result = []
for (let i = 0; i < arr.length; i += chunkSize) {
const chunk = arr.slice(i, i + chunkSize)
const filtered = chunk.filter(filterFn)
if (filtered.length) result.push(...filtered)
}
return result
}
}
// 使用示例
const filteredUsers = ArrayFilters.uniqueBy(users, 'id')
在Vue3项目中使用时,可以将其挂载到app实例上:
javascript复制// main.js
import { ArrayFilters } from './utils/array-filters'
app.config.globalProperties.$filters = ArrayFilters
6. 常见问题解决方案
6.1 内存泄漏问题
问题现象:在SPA应用中长时间使用过滤器导致内存增长
解决方案:
javascript复制// 使用WeakMap存储临时过滤结果
const memoizedFilter = (() => {
const cache = new WeakMap()
return (arr, filterFn) => {
if (!cache.has(arr)) {
cache.set(arr, arr.filter(filterFn))
}
return cache.get(arr)
}
})()
6.2 大数组性能优化
优化方案:
javascript复制const parallelFilter = async (arr, predicate, workerCount = 4) => {
const chunkSize = Math.ceil(arr.length / workerCount)
const chunks = Array.from({ length: workerCount }, (_, i) =>
arr.slice(i * chunkSize, (i + 1) * chunkSize)
)
const workers = chunks.map(chunk =>
new Promise(resolve => {
const worker = new Worker('./filterWorker.js')
worker.postMessage({ chunk, predicate: predicate.toString() })
worker.onmessage = e => resolve(e.data)
})
)
return (await Promise.all(workers)).flat()
}
7. 测试策略
7.1 单元测试示例
javascript复制describe('Array Filters', () => {
test('multiFilter should return matching items', () => {
const users = [
{ id: 1, name: 'Alice', active: true },
{ id: 2, name: 'Bob', active: false }
]
const result = multiFilter(users, { active: true })
expect(result).toEqual([{ id: 1, name: 'Alice', active: true }])
})
})
7.2 基准测试对比
javascript复制const testData = Array.from({ length: 1e6 }, (_, i) => ({
id: i,
value: Math.random()
}))
const results = {
native: benchmarkFilter(arr => arr.filter(x => x.value > 0.5), testData),
optimized: benchmarkFilter(parallelFilter, testData)
}
console.table(results)
8. 生态整合方案
8.1 与Vuex/Pinia集成
javascript复制// store.js
export const useFilterStore = defineStore('filters', {
state: () => ({
userFilters: {},
data: []
}),
getters: {
filteredData(state) {
return state.data.filter(item =>
Object.entries(state.userFilters).every(([key, val]) =>
val ? item[key].includes(val) : true
)
)
}
}
})
8.2 与GraphQL配合
javascript复制const buildGraphQLFilterInput = (filters) => {
const gqlFilters = {}
Object.entries(filters).forEach(([key, value]) => {
if (value !== undefined) {
gqlFilters[key] = { eq: value }
}
})
return { filter: gqlFilters }
}
9. 类型安全实现
对于TypeScript项目,添加完整的类型定义:
typescript复制interface FilterOptions<T> {
condition: (item: T) => boolean
limit?: number
}
function typedFilter<T>(arr: T[], options: FilterOptions<T>): T[] {
let result = arr.filter(options.condition)
if (options.limit) result = result.slice(0, options.limit)
return result
}
// 使用示例
interface User {
id: number
name: string
}
const users: User[] = [{ id: 1, name: 'Alice' }]
const filtered = typedFilter(users, {
condition: user => user.id > 0
})
10. 可视化过滤构建器
最后分享一个动态过滤条件生成器的实现:
javascript复制const createFilterBuilder = (fields) => {
const state = reactive({
conditions: [],
logic: 'AND'
})
const addCondition = (field, operator, value) => {
state.conditions.push({ field, operator, value })
}
const applyFilter = (data) => {
return data.filter(item => {
const tests = state.conditions.map(({ field, operator, value }) => {
switch (operator) {
case 'equals': return item[field] === value
case 'contains': return item[field].includes(value)
// 其他操作符...
}
})
return state.logic === 'AND'
? tests.every(Boolean)
: tests.some(Boolean)
})
}
return { state, addCondition, applyFilter }
}
这个实现可以轻松集成到管理后台系统中,让用户通过UI界面构建复杂的过滤条件。在实际项目中,我通常会结合Vue3的transition组件添加过滤动画效果,提升用户体验。
