通用JavaScript实现:基于任意层级属性过滤对象数组
如何通用地基于任意层级属性过滤对象列表(未知属性名称)
问题分析
你遇到的核心问题是嵌套对象的属性匹配:直接用Object.keys()遍历第一层属性时,没法处理过滤条件里的深层嵌套(比如address.zip),而且对象是引用类型,直接比较整个子对象肯定不相等,得逐个检查嵌套里的每个属性。
解决方案:递归匹配过滤条件
我们可以写一个递归辅助函数,用来检查单个对象是否满足所有层级的过滤条件,再结合数组的filter()方法实现列表过滤。
1. 递归匹配函数
这个函数会遍历过滤条件的每个属性,遇到嵌套对象就递归检查下一层:
function matchesFilter(obj, filterObj) { // 遍历过滤条件的每一个属性键 for (const key of Object.keys(filterObj)) { const filterVal = filterObj[key]; const objVal = obj[key]; // 如果过滤值是对象(且不是null),递归检查下一层级 if (typeof filterVal === 'object' && filterVal !== null) { // 目标对象没有对应属性,或者递归检查不通过,直接返回不匹配 if (!objVal || !matchesFilter(objVal, filterVal)) { return false; } } else { // 非对象类型,直接比较值是否相等 if (objVal !== filterVal) { return false; } } } // 所有过滤条件都满足,返回匹配 return true; }
2. 应用到列表过滤
用上面的辅助函数配合Array.filter(),就能轻松过滤你的对象列表:
var list = [ { name: 'Alice', address: { zip: '10000', street: '71 Pilgrim Avenue' } }, { name: 'Bob', address: { zip: '20000', street: '44 Shirley Ave' } }, { name: 'Charlie', address: { zip: '30000', street: '4 Goldfield Rd' } }, ]; var filter = { address: { zip: '10000' } }; // 执行过滤 const filteredResult = list.filter(item => matchesFilter(item, filter)); console.log(filteredResult);
运行后会得到你期望的结果:
[{ name: 'Alice', address: { zip: '10000', street: '71 Pilgrim Avenue' } }]
扩展测试:多属性多层级过滤
这个方案支持更复杂的过滤条件,比如同时匹配name和深层的street:
var complexFilter = { name: 'Bob', address: { street: '44 Shirley Ave' } }; const complexResult = list.filter(item => matchesFilter(item, complexFilter)); // 输出: [{ name: 'Bob', address: { zip: '20000', street: '44 Shirley Ave' } }]
为什么你之前的方法有问题?
你提到用Object.keys()时遇到属性值以数组形式返回?应该是没处理嵌套对象的情况:比如直接拿到filter.address后,直接和item.address比较——但两个对象是不同的引用,即使内容一样也会返回false。而递归函数会逐个检查嵌套里的每个属性值,就能正确匹配。
内容的提问来源于stack exchange,提问作者Ezeon
相关产品推荐
相关产品推荐

