使用数组元素定位另一数组索引时,原数组数据为何变更?
问题分析与解决:CASHVALUES数组意外被修改的原因
核心问题出在这两行代码:
const currentDenomination = CASHVALUES[i][1]; change[change.indexOf(CASHVALUES[i])][1] += currentDenomination;
每次执行这段代码时,CASHVALUES[i][1]的值都会意外翻倍。原本预期只有change数组的数据会被修改,尝试将CASHVALUES的克隆值赋值给currentDenomination也无法解决问题。
完整问题代码片段:
function checkCashRegister(price, cash, cid) { let cid = [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]; const CASHVALUES = [["ONE HUNDRED", 100], ["TWENTY", 20], ["TEN", 10], ["FIVE", 5], ["ONE", 1], ["QUARTER", 0.25], ["DIME", 0.1], ["NICKEL", 0.05], ["PENNY", 0.01]]; let changeDue = (cash - price); const TotalChangeDue = changeDue let change = []; let status = "OPEN"; cid.reverse(); for(let i=0;i<CASHVALUES.length;i++) { const currentDenomination = CASHVALUES[i][1]; if(changeDue >= currentDenomination) { if(cid[i][1] > 0) { cid[i][1] -= currentDenomination; cid[i][1] = cid[i][1].toFixed(2); changeDue -= currentDenomination; changeDue = changeDue.toFixed(2); if(!change.includes(CASHVALUES[i])) { change.push(CASHVALUES[i]); } else { change[change.indexOf(CASHVALUES[i])][1] += currentDenomination; } i--; } } } }
问题根源
这是典型的引用类型赋值导致的问题:
CASHVALUES中的元素是数组(属于引用类型),当你执行change.push(CASHVALUES[i])时,并没有把数组的副本加入change,而是把该数组的内存引用直接添加进去了。- 这意味着
change里的元素和CASHVALUES里的对应元素指向的是同一个内存地址。当你执行change[...][1] += currentDenomination时,本质上是在修改CASHVALUES[i][1]本身,因为两者是同一个引用。 - 你尝试克隆
currentDenomination没用,因为currentDenomination是数值(基本类型),克隆它无法解决数组引用共享的问题。
解决方案
要解决这个问题,需要在将CASHVALUES的元素加入change时,创建数组的副本,而不是直接添加引用。同时,改用币种名称判断元素是否存在(引用比较不可靠),修改后的核心逻辑如下:
// 替换原有的if-else判断逻辑 const denominationName = CASHVALUES[i][0]; const existingItemIndex = change.findIndex(item => item[0] === denominationName); if (existingItemIndex === -1) { // 创建新数组副本加入change,避免引用共享 change.push([denominationName, currentDenomination]); } else { // 修改change中的对应项,不会影响CASHVALUES change[existingItemIndex][1] += currentDenomination; }
另外还有两个额外的坑需要修正:
cid[i][1].toFixed(2)和changeDue.toFixed(2)会把数值转为字符串,后续的加减运算会出现字符串拼接的错误,建议保留数值类型,仅在最终输出结果时进行格式化。- 原代码中
change.includes(CASHVALUES[i])是引用比较,即使两个数组内容完全一致,只要引用不同就会返回false,改用币种名称判断更可靠。
内容的提问来源于stack exchange,提问作者Kyle Boyd
相关产品推荐
相关产品推荐

