JS遍历两数组按条件修改属性值时展开运算符不生效问题
问题根因
你遇到的问题和展开运算符本身无关,是对Array.filter()的执行逻辑存在理解偏差:
filter方法的核心作用是筛选元素,它的回调返回值仅会被当作布尔值判断:返回真值就保留当前遍历的原始元素到结果数组,返回假值就跳过该元素。回调里return的任何对象、值都不会用来替换原始元素。- 你写的嵌套filter逻辑里,id匹配时return的展开新对象,仅被当作「真值」触发了外层filter的保留逻辑,这个新对象创建完成后没有被赋值给任何变量、也没有被存入结果数组,直接被丢弃了,自然不会出现在最终的result里。你在return前打印能看到正确值,恰恰说明展开运算符正常工作、成功生成了属性更新后的新对象,只是这个对象没被用到。
- 注释里的
x.email = y.name能生效,是因为这行代码直接修改了result2原数组里的对象本身,外层filter保留原始x元素时,x的email属性已经被修改,所以能看到效果,但这种写法会直接改动原始数据源,属于有副作用的写法。
正确实现方案
要实现「id匹配时更新元素指定属性、最终得到更新后的数组」的需求,不要用filter做数据修改:筛选匹配项用find,遍历生成新数组用map,同时用展开运算符生成新对象避免修改原数据,参考代码如下:
var result1 = [ {id:1, name:'Sandra', type:'user', username:'sandra'}, {id:2, name:'John', type:'admin', username:'johnny2'}, {id:3, name:'Peter', type:'user', username:'pete'}, {id:4, name:'Bobby', type:'user', username:'be_bob'} ]; var result2 = [ {id:2, name:'John', email:'johnny@example.com',fullName:'Test1'}, {id:4, name:'Bobby', email:'bobby@example.com',fulname:'Test2'} ]; var result = result2.map(function(x) { var match = result1.find(function(y) { return y.id === x.id; }); // 匹配到对应id时,用展开运算符生成email更新后的新对象,不修改原数组 return match ? {...x, email: match.name} : x; }); console.log(result);
补充:数组方法要按设计目的使用:
filter用于筛选、map用于遍历生成新结构数组、find用于查找匹配项、reduce用于聚合计算,不要混用方法做超出设计目标的操作,否则很容易出现预期外的结果。
内容的提问来源于stack exchange,提问作者ashwini
相关产品推荐
相关产品推荐

