You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JS新手求助:数组permanentDeck值意外被修改问题排查

数组无显式修改时值变更问题定位

根因

JavaScript中数组、对象属于引用类型,直接使用=赋值不会复制数据,只会让多个变量指向内存中同一个数组实例。你代码中permanentDeck、deck、drawPile三个变量最终都指向了同一个初始数组,所有对drawPile的修改(洗牌、抽卡pop)都会直接作用在这个共享数组上,导致你观察到permanentDeck的卡牌被"莫名移除"。

具体问题代码行

  • 第一处:永久牌组赋值未做拷贝
switch(playerClass){
    case "Warrior":
        permanentDeck = starterWarriorDeck // 直接赋值引用,未复制数组内容
}
  • 第二处:战斗牌组直接指向永久牌组
function startBattle(){
    deck = permanentDeck; // deck和permanentDeck指向同一数组
    restockDrawPile();
}
  • 第三处:洗牌逻辑原地修改传入数组,且抽牌堆直接引用战斗牌组
function shuffle(array){
    // 该逻辑直接在原数组上交换元素,属于原地修改,不会创建新数组
    let currentIndex = array.length,  randomIndex;
    while (currentIndex != 0) {
      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex--;
      [array[currentIndex], array[randomIndex]] = [
        array[randomIndex], array[currentIndex]];
    }
    return array;
}
function restockDrawPile(){
    drawPile = shuffle(deck); // drawPile拿到的还是原数组引用
}
  • 第四处:抽卡使用pop原地删除数组元素
let nextCard = drawPile.pop(); // pop会直接删除原数组最后一个元素,直接修改共享的原数组

整个调用链下来,抽5张卡的操作本质是从permanentDeck指向的原数组里删了5个元素,所以最终打印permanentDeck时只剩2张卡。

修复方案

所有需要独立操作数组的场景,对原数组做浅拷贝切断引用关系即可(数组内的卡牌对象不需要修改属性,浅拷贝完全满足需求):

  1. 初始化永久牌组时复制初始卡牌
switch(playerClass){
    case "Warrior":
        permanentDeck = [...starterWarriorDeck] // 用展开运算符做浅拷贝
}
  1. 每次开战初始化战斗牌组时,从永久牌组拷贝新数组
function startBattle(){
    deck = [...permanentDeck]; // 每次战斗生成独立的牌组副本,不修改永久牌组
    restockDrawPile();
}
  1. 洗牌时传入战斗牌组的副本,避免打乱原战斗牌组顺序
function restockDrawPile(){
    drawPile = shuffle([...deck]); // 拷贝后再打乱,抽牌堆操作独立于战斗牌组
}

修复后permanentDeck会始终保持7张初始卡牌的状态,不会被洗牌、抽卡逻辑影响。


内容的提问来源于stack exchange,提问作者ArthurIscariot

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:15:48