Angular/TypeScript处理API图表数据时数组输出异常问题求助
你碰到的这个控制台显示异常+数据被覆盖的问题,本质是数组引用复用导致的,浏览器控制台的“诡异”表现只是这个问题的外在体现而已。
先解释控制台的奇怪现象
浏览器控制台打印引用类型(比如数组、对象)时,初始显示的是打印那一刻的“快照”,但当你展开它时,会去读取这个对象的当前状态。因为你所有的dataset.data都指向同一个tempRates数组,最后这个数组被修改成了全1,所以展开后看到的都是1,而初始快照是当时的正确值——这不是控制台bug,是它的工作机制。
代码里的核心问题
你在循环中一直复用同一个tempRates数组,每次往this.data.datasets里push的时候,传递的是这个数组的引用,而不是它的副本。这就相当于所有dataset的data都“共享”同一个数组,后续对tempRates的清空(tempRates.length = 0)或者修改,都会同步影响之前所有已经push进去的数组引用。最后一个数组没被清空,所以它的值保留了全1,前面的数组因为引用指向同一个对象,也跟着变成了全1。
修复方案
解决的关键是给每个dataset的data提供独立的数组实例,不要复用同一个数组。有两种简单的方式:
方案1:每次循环创建新的tempRates
把tempRates的初始化放到循环内部,这样每次迭代都是全新的数组:
let i = 0; // 确保i提前初始化 // 先处理日期标签 Object.keys(data.rates).forEach((key) => { this.data.labels.push(key); }); // 处理汇率数据 Object.values(data.rates).forEach((value) => { // 每次循环新建数组,不再复用 const tempRates: number[] = []; const tempCurrency = Object.keys(value)[i]; Object.values(data.rates).forEach((rate) => { if (tempCurrency === Object.keys(rate)[i]) { tempRates.push(rate[tempCurrency]); } }); // 打印的时候也可以用扩展运算符创建副本,避免控制台显示误导 console.log("log before push", [...tempRates]); this.data.datasets.push({ label: tempCurrency, data: tempRates, // 现在每个data都是独立的数组 }); i++; });
方案2:在push时创建数组副本
如果你想保留原来的变量结构,就在往datasets里push的时候,用扩展运算符或者Array.from()创建数组的副本:
let i = 0; const tempRates: number[] = []; Object.keys(data.rates).forEach((key) => { this.data.labels.push(key); }); Object.values(data.rates).forEach((value) => { tempRates.length = 0; // 清空数组 const tempCurrency = Object.keys(value)[i]; Object.values(data.rates).forEach((rate) => { if (tempCurrency === Object.keys(rate)[i]) { tempRates.push(rate[tempCurrency]); } }); console.log("log before push", [...tempRates]); this.data.datasets.push({ label: tempCurrency, data: [...tempRates], // 传递副本,而非引用 }); i++; });
额外小提示
以后调试引用类型的时候,要是想看到打印那一刻的真实值,最好打印它的副本(比如[...tempRates]或者JSON.parse(JSON.stringify(tempRates))),这样就不会被后续的修改影响控制台的显示结果了。
内容的提问来源于stack exchange,提问作者Imra Kočiš

