从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
相关产品推荐
相关产品推荐

