RxJS中Observable.from配合map修改元素致原数组变更问题咨询
问题原因:对象引用传递
这是个典型的JavaScript对象引用问题,跟RxJS本身关系不大,咱们来拆解一下:
你代码里的Observable.from(myArr)并没有创建原数组对象的副本,它只是把数组里的每个对象引用依次发射出去。也就是说,map操作符里的el变量,直接指向原数组myArr里的对应对象——你修改el.a,本质上就是在修改原数组里那个对象的属性。
具体执行流程是这样的:
- 第一次处理原数组的
{a: 'Apple'}:把它的a改成Coke,此时原数组第一个元素已经变成{a: 'Coke'}; - 第二次处理原数组的
{a: 'Banana'}:修改它的a为Coke,原数组第二个元素也跟着变化,此时原数组前两个元素都是Coke; - 第三次处理
{a: 'Carrot'}:修改后原数组三个元素全变成Coke。
所以每次打印myArr时,都会看到已经被修改过的结果。
解决方案:创建新对象避免修改原引用
要解决这个问题,你需要在map里返回一个新的对象,而不是直接修改原对象的属性。这里有几种常用方法:
1. 对象展开语法(ES6+推荐)
let myArr = [{a: 'Apple'}, {a: 'Banana'}, {a: 'Carrot'}]; let stream = Observable .from(myArr) .map( el => { const newEl = {...el, a: 'Coke'}; // 创建新对象,覆盖a属性 console.log(`interim----- ${JSON.stringify(newEl)} ||| ${JSON.stringify(myArr)}`); return newEl; }); stream.subscribe( elm => elm );
2. 使用Object.assign
.map( el => { const newEl = Object.assign({}, el, {a: 'Coke'}); // 以空对象为目标,合并原对象和新属性 console.log(`interim----- ${JSON.stringify(newEl)} ||| ${JSON.stringify(myArr)}`); return newEl; });
3. 深拷贝(针对嵌套对象)
如果你的对象有多层嵌套结构,上面的浅拷贝方法就不够用了,可以用深拷贝:
.map( el => { const newEl = JSON.parse(JSON.stringify(el)); // 通过JSON序列化实现深拷贝 newEl.a = 'Coke'; console.log(`interim----- ${JSON.stringify(newEl)} ||| ${JSON.stringify(myArr)}`); return newEl; });
预期输出
修改后控制台会输出:
interim----- {"a":"Coke"} ||| [{"a":"Apple"},{"a":"Banana"},{"a":"Carrot"}]
interim----- {"a":"Coke"} ||| [{"a":"Apple"},{"a":"Banana"},{"a":"Carrot"}]
interim----- {"a":"Coke"} ||| [{"a":"Apple"},{"a":"Banana"},{"a":"Carrot"}]
这样原数组就不会被修改了,因为我们每次处理的都是新创建的对象,和原数组里的对象没有引用关系。
内容的提问来源于stack exchange,提问作者zaggi
相关产品推荐
相关产品推荐

