请求解析ES5中嵌套filter的代码工作原理
解析这段数组差异计算的代码
首先先把你的代码贴出来方便对照:
const arr1 = [{"id":1,"name":"jhon"},{"id":2,"name":"max"},{"id":3,"name":"fer"}]; const arr2 = [8, 9]; var diffArray = arr2.filter(x => !arr1.filter(y => y.id === x).length); console.log(diffArray); // 输出: [8, 9]
接下来一步步拆解每部分的作用,彻底搞懂它的逻辑:
1. 先看初始定义的两个数组
arr1:是一个包含对象元素的数组,每个对象都有id和name属性,id值分别为1、2、3。arr2:是一个简单的数字数组,元素是8和9。
2. 核心逻辑:diffArray的计算过程
这行代码嵌套使用了两个filter方法,我们从内层到外层拆解更清晰:
内层的arr1.filter(y => y.id === x)
- 这里的
x是外层arr2.filter当前遍历到的元素(比如第一次是8,第二次是9)。 - 这个内层
filter会遍历arr1的所有对象,找出id属性等于x的对象,返回一个新数组。 - 如果找不到匹配的对象,就会返回一个空数组,空数组的
length属性是0。
外层的arr2.filter(x => !arr1.filter(...).length)
- 外层
filter的作用是遍历arr2的每个元素,判断一个条件:!内层filter返回数组的length。 - 这里的
!是逻辑非运算符:- 如果内层返回空数组(length=0),
!0等于true,说明当前x在arr1的所有对象id里都找不到匹配,这个x就会被保留到diffArray里。 - 如果内层找到了匹配的对象(length≥1),
!length等于false,这个x会被过滤掉。
- 如果内层返回空数组(length=0),
3. 代入具体值走一遍流程
我们拿arr2里的第一个元素8举例:
- 内层
arr1.filter(y => y.id === 8)遍历arr1的三个对象,它们的id是1、2、3,都不等于8,所以返回空数组[]。 - 空数组的length是0,
!0等于true,所以8会被外层filter保留。 - 再看第二个元素9,逻辑和8完全一致,内层找不到匹配,所以也被保留。
- 最终
diffArray就是[8, 9],和console.log的输出结果一致。
小补充:写法的优化方向
虽然这段代码逻辑没问题,但效率不算高——因为arr2里的每个元素都要完整遍历一遍arr1。如果数组元素很多,更高效的做法是先把arr1的id存到一个Set里,再用Set的has方法判断,比如:
const arr1Ids = new Set(arr1.map(item => item.id)); const diffArray = arr2.filter(x => !arr1Ids.has(x));
这样时间复杂度会从O(n*m)降到O(n+m),属于性能优化的小技巧~
内容的提问来源于stack exchange,提问作者Rohan Singh
相关产品推荐
相关产品推荐

