如何在嵌套循环中实现递增乘数运算?问题排查与解决
问题描述
我有一个包含嵌套对象的结构:
const object = { id: 1, innerArr: [ { key: 50 }, { key: 20 } ] }
我想把这个对象推入新数组共7次,每次迭代用递增的乘数计算key值,写了如下代码:
const arr = []; let increment = 0.85; for (let i = 0; i < 7; i++) { const { id } = object; object.innerArr.forEach(obj => { obj.key *= increment; }) arr.push({ id, innerArr: object.innerArr }) increment += 0.05; // 依次是0.9, 0.95... }
预期输出是每次迭代的key分别用当前乘数乘以原始值(比如第一次500.85=42.5,第二次500.9=45等),但实际所有数组项的key都只应用了最后一次的乘数,请问怎么实现预期效果?问题出在哪?
问题根源
- JavaScript里对象、数组都是引用类型,你每次修改
object.innerArr里的obj.key,都是直接修改原始对象里的嵌套数据; - 每次
push到新数组的innerArr并不是新数组,只是原始innerArr的引用。所以数组里的所有项都指向同一个数组对象,最后所有项都会显示最后一次修改后的结果; - 另外你每次迭代都在修改原始
key的值,相当于每次都是在上一次修改后的基础上再乘新乘数,这也和你“用原始值乘当前乘数”的预期不符。
解决方案
要实现预期效果,需要做到两点:每次基于原始值计算,并且为每个新对象创建独立的innerArr副本。
方案1:保存原始值,每次生成新数组
先把原始key值存下来,每次迭代用原始值乘以当前乘数,同时创建全新的嵌套对象和数组:
const object = { id: 1, innerArr: [ { key: 50 }, { key: 20 } ] }; // 提前保存原始key值,避免后续修改影响计算 const originalKeys = object.innerArr.map(item => item.key); const arr = []; let increment = 0.85; for (let i = 0; i < 7; i++) { // 每次生成新的innerArr和嵌套对象 const newInnerArr = originalKeys.map(key => ({ key: key * increment })); arr.push({ id: object.id, innerArr: newInnerArr }); increment += 0.05; }
方案2:深拷贝原始对象后再修改
如果不想单独保存原始值,可以每次迭代都深拷贝原始对象,再修改拷贝后的对象:
const object = { id: 1, innerArr: [ { key: 50 }, { key: 20 } ] }; const arr = []; let increment = 0.85; for (let i = 0; i < 7; i++) { // 用JSON方法深拷贝(适合无函数、循环引用的简单对象) const newObj = JSON.parse(JSON.stringify(object)); // 修改拷贝后的对象的key值 newObj.innerArr.forEach(obj => { obj.key *= increment; }); arr.push(newObj); increment += 0.05; }
注意:
JSON.parse(JSON.stringify())不支持拷贝函数、循环引用、Symbol等特殊类型。如果你的对象结构更复杂,可以自己写递归深拷贝函数,或者用成熟的第三方工具方法。
内容的提问来源于stack exchange,提问作者liav
相关产品推荐
相关产品推荐

