JS将对象push到数组后与原对象内容不一致,是什么原因导致的?
问题根因
1. 对象引用类型特性导致数据被覆盖
JavaScript 中的普通对象属于引用数据类型,你遍历SP500拿到的y是原数组中对象的内存引用,执行data.push(y)时只是把这个引用存进了data数组,并没有独立复制一份对象。
你在循环里直接给y.cumulativeReturn赋值,本质是修改原数组中对象的属性,之前已经存到data里的引用指向的是同一个原对象,所以属性会同步被后续循环的计算结果覆盖。
另外你调用的SP500.reverse()是原地修改方法,会直接改变原始SP500数组的元素顺序,还会污染全局的原始数据。
2. 浏览器控制台的懒加载特性
浏览器console.log打印对象/数组时,输出的是对象的引用快照,你点击展开打印结果时才会读取对象当前的最新属性值,不是执行log语句那一刻的属性值,这也会让你看到的打印结果和预期执行时刻的数值不一致。
修复代码
只需要在操作时避免修改原对象,推入data时存入独立的新对象即可,同时反转数组前先复制原数组避免污染原始数据:
export const fetchSP500 = (year) => { let data = []; let cumulativeReturn = 1; // 复制原数组后再反转,不修改原始SP500 [...SP500].reverse().forEach(y => { cumulativeReturn *= ((y.totalReturn * .01) + 1); const curCumulative = ((cumulativeReturn - 1) * 100); if (y.year >= year[0] && y.year <= year[1]) { // 创建新对象存入,不修改原y对象 data.push({ ...y, cumulativeReturn: curCumulative }); } }) return data; }
如果需要打印准确的时刻快照,可以把对象转成JSON再转回对象打印,规避控制台懒加载的影响:
console.log('当前data快照:', JSON.parse(JSON.stringify(data)))
内容的提问来源于stack exchange,提问作者Walter
相关产品推荐
相关产品推荐

