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

从Observable取数存入数组后删除元素,原Observable数据也被删除?

问题描述

我尝试从Observable中获取数据并存入数组,随后使用splice方法从数组中删除一个元素,但Observable中的对应元素也被删除了,请问哪里操作有误?

假设Observable的数据结构如下:

dataObs = {
   values:[{id: 1, name: 'orange'},
           {id: 2, name: 'apple'},
           {id: 3, name: 'peach'}], 
   // 其他属性...
}

我的代码:

let dataArr = new Array<any>;

this.dataObs.subscribe(val => dataArr = val);
dataArr.forEach((element, index) => {
   if(element.id == 1) dataArr.splice(index, 1) // 删除数组中的orange
});

结果Observable里的orange也被删除了:

dataObs = {
   values:[{id: 2, name: 'apple'},
           {id: 3, name: 'peach'}], 
   // 其他属性...
}
问题原因

你直接将Observable返回的对象赋值给dataArr,而在JavaScript/TypeScript中,对象和数组都是引用类型——这意味着dataArr并没有创建新的数组副本,而是和Observable里的values数组指向同一个内存地址。因此你对dataArr调用splice时,本质上是在修改原Observable中的数组。

另外还有个潜在问题:Observable的订阅是异步操作,你的forEach代码可能会在dataArr被赋值前就执行,不过从结果来看此次订阅已同步完成,但这个异步逻辑问题需要注意。

解决方法

要避免修改原数据,你需要创建原数组的浅拷贝;如果数组元素是复杂对象且后续要修改其内部属性,则需要进行深拷贝。

方法1:用扩展运算符创建浅拷贝

let dataArr: any[] = [];

this.dataObs.subscribe(val => {
  // 对val.values做浅拷贝后赋值给dataArr
  dataArr = [...val.values];
});

方法2:用Array.from创建拷贝

let dataArr: any[] = [];

this.dataObs.subscribe(val => {
  dataArr = Array.from(val.values);
});

方法3:深拷贝(针对复杂对象场景)

如果后续需要修改数组内对象的属性且不想影响原数据,可使用深拷贝:

let dataArr: any[] = [];

this.dataObs.subscribe(val => {
  dataArr = JSON.parse(JSON.stringify(val.values));
});

注意:JSON.parse(JSON.stringify)不支持函数、Symbol等特殊类型,若数据包含这类内容,建议使用专门的深拷贝工具(如Lodash的cloneDeep)。

同时,为避免异步问题,建议将删除逻辑放在订阅回调内部,确保数据已被正确获取:

let dataArr: any[] = [];

this.dataObs.subscribe(val => {
  dataArr = [...val.values];
  // 在回调内处理删除操作
  dataArr.forEach((element, index) => {
    if(element.id === 1) {
      dataArr.splice(index, 1);
    }
  });
});

内容的提问来源于stack exchange,提问作者Sachio Shaan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 22:55:23