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

如何修复点击按钮时遍历全部建筑对象的JavaScript代码问题

修复Soul Clicker中建筑购买按钮的遍历问题

问题描述

开发类似Cookie Clicker的Soul Clicker游戏时,改用对象数组存储建筑数据优化代码后,点击购买按钮会遍历所有建筑对象,而非仅处理点击对应的建筑,导致逻辑错误。

解决方案

核心是让每个按钮与对应的buildings数组索引绑定,点击时仅处理对应索引的建筑对象:

关键修改点

  • 利用forEach的第二个参数获取按钮对应的数组索引,避免遍历所有建筑
  • 修复变量名冲突(原代码中forEach参数和循环变量都用i,导致逻辑混乱)
  • 点击事件中直接通过索引定位目标建筑,只执行该建筑的购买逻辑

修改后的JavaScript代码

let soulAmount = 0;
let soulAddition = 1;
let grabSps = document.querySelector(".sps").innerHTML;
let sps = parseInt(grabSps);
let upgrade1GOT = false;
let upgrade2GOT = false;

let buildings = [
    {
        "name": "Collector",
        "upgradecost": 10,
        "sps": 1
    },
    {
        "name": "Hunter",
        "upgradecost": 100,
        "sps": 5
    }
];

let upgrades = document.querySelectorAll(".upgrade");

// 关键修改:使用forEach的索引参数绑定对应建筑
upgrades.forEach(function (button, index) {
    button.addEventListener("click", function () {
        const building = buildings[index];
        // 只处理当前点击按钮对应的建筑
        if (soulAmount >= building.upgradecost) {
            sps += building.sps;
            soulAmount -= building.upgradecost;
            document.querySelector(".souls_amount").innerHTML = soulAmount;
            document.querySelector(".sps").innerHTML = sps;
            // 升级成本提升20%
            building.upgradecost = Math.round(building.upgradecost * 1.2);
            console.log(building.upgradecost);
        }
    })
});

window.setInterval(function() {
    document.querySelector(".souls_amount").innerHTML = soulAmount;
    document.querySelector(".upgrade1-cost").innerHTML = buildings[0].upgradecost;
    document.querySelector(".upgrade2-cost").innerHTML = buildings[1].upgradecost;
    validateSoul();
}, 1);

function validateSoul(){
    if(soulAmount >= 10 && soulAmount <= 19 && upgrade1GOT == false){
        document.getElementById("collect100").style.display = "block"
        document.getElementById("collect100").disabled = true;
    } else if (soulAmount >= 20 && upgrade1GOT == false){
        document.getElementById("collect100").disabled = false;
    }

    if(soulAmount >= 100 && soulAmount <= 199 && upgrade2GOT == false){
        document.getElementById("collect1000").style.display = "block"
        document.getElementById("collect1000").disabled = true;
    } else if (soulAmount >= 200 && upgrade2GOT == false){
        document.getElementById("collect1000").disabled = false;
    }

    // 优化按钮状态判断,利用索引循环简化
    upgrades.forEach((button, index) => {
        button.disabled = soulAmount < buildings[index].upgradecost;
        // 处理Hunter的显示逻辑
        if(index === 1 && !button.disabled){
            document.querySelector(".soul__shop--name").innerHTML = buildings[1].name;
        }
    });
}

function getSoul() {
    soulAmount += soulAddition;
    document.querySelector(".souls_amount").innerHTML = soulAmount;
    return soulAmount;
}

// 补充缺失的成就函数(原HTML中调用但未定义)
function achievement1() {
    upgrade1GOT = true;
    document.getElementById("collect100").style.display = "none";
    // 可添加成就奖励逻辑,比如提升soulAddition
}

function achievement2() {
    upgrade2GOT = true;
    document.getElementById("collect1000").style.display = "none";
    // 可添加成就奖励逻辑
}

关键知识点说明

  • forEach的参数:querySelectorAll返回的NodeList调用forEach时,第二个参数是当前元素的索引,可用来关联数组中的对应对象
  • 变量作用域:原代码中forEach的参数名和循环变量都用i,导致变量冲突覆盖,使用不同命名(如button、index)可避免此问题
  • 事件绑定上下文:通过在forEach中绑定索引,点击事件能直接获取到对应建筑,无需遍历整个数组,提升性能并避免逻辑错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 08:48:09