Array slice()返回引用而非值的问题及代码场景求助
嘿,我完全懂你碰到的这个坑!核心问题在于slice()方法做的是浅拷贝:它会创建一个新数组,但数组里的每个对象元素依然和原数组的对应对象共享引用。所以你把LINECHART2_DATA.series.slice()赋值给bed.seriesContainer后,修改bed.seriesContainer里的series.data,其实也在改动LINECHART2_DATA里的原始data数组,自然会导致数据处理异常。
解决办法:实现深拷贝
我们需要对数组里的每个对象也进行拷贝,彻底断开和原数据的引用链接,这里有几种实用方案:
方案1:手动浅拷贝每个对象(推荐,可控性强)
用map()遍历原数组,配合对象展开运算符...复制每个series的属性,同时单独初始化data为新数组:
bed.seriesContainer = LINECHART2_DATA.series.map(series => ({ ...series, data: [] // 直接初始化空数组,和原数据断开引用 }));
如果需要保留原data的副本(而不是清空),可以改成data: [...series.data],这样data也是新数组,不会影响原始数据。
方案2:JSON序列化反序列化(适合简单结构)
如果你的series对象结构比较简单(没有函数、undefined、Symbol或日期对象),可以用JSON.parse(JSON.stringify())做深拷贝:
bed.seriesContainer = JSON.parse(JSON.stringify(LINECHART2_DATA.series));
⚠️ 注意:这个方法有局限性——函数、undefined、Symbol会被忽略,日期对象会被转成字符串,复杂场景不推荐。
方案3:使用第三方库(适合复杂嵌套结构)
如果你的数据嵌套很深,可以用Lodash的_.cloneDeep()方法,它能处理各种复杂数据类型的深拷贝:
import _ from 'lodash'; bed.seriesContainer = _.cloneDeep(LINECHART2_DATA.series);
适配你的代码场景
修改后的prepareLineChartDataContainer方法可以写成这样:
function prepareLineChartDataContainer(bed) { // 为新床位清理数据 if (bed.seriesContainer == null) { // 深拷贝每个series对象,彻底断开引用 bed.seriesContainer = LINECHART2_DATA.series.map(series => ({ ...series, data: [] })); } else { bed.seriesContainer.forEach(series => { series.data.length = 0; // 清空现有数据,此时不会影响原LINECHART2_DATA }); } }
这样修改后,每个bed的seriesContainer都是独立的对象数组,修改数据时再也不会干扰原始的LINECHART2_DATA了。
内容的提问来源于stack exchange,提问作者Jesper

