You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:23:45