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

跨原型创建过滤器及Team类kick方法同类型攻击问题排查

问题解答

一、修复Team.kick方法的错误与实现优先攻击逻辑

首先,你碰到的TypeError: sameTypeUnit.__proto__ is not a function是因为错误把__proto__当成函数调用了——__proto__是指向对象原型的属性,根本不是可执行的函数。而且原kick方法的逻辑混乱,比如遍历成员后只保留最后一个,攻击逻辑完全不符合需求,我们来一步步重构:

1. 核心逻辑明确

我们要实现的规则是:

  • 团队轮流让存活成员发起攻击
  • 攻击方优先锁定敌方同类型且存活的目标
  • 若同类型目标全部阵亡,则随机挑选敌方任意存活目标

2. 修复后的完整kick方法代码

Team.prototype.kick = function(targetTeam) {
    // 先找到当前团队下一个能攻击的存活成员
    let activeMember = null;
    do {
        activeMember = this.members[this.activeMember];
        this.activeMember = (this.activeMember + 1) % this.members.length;
    } while (!activeMember.isAlive());

    // 筛选敌方同类型的存活目标
    const sameTypeTargets = targetTeam.members.filter(unit => {
        return unit.isAlive() && unit.type === activeMember.type;
    });

    // 确定最终攻击目标:优先同类型,无则随机选存活目标
    let target;
    if (sameTypeTargets.length > 0) {
        target = sameTypeTargets[Math.floor(Math.random() * sameTypeTargets.length)];
    } else {
        const allAliveTargets = targetTeam.members.filter(unit => unit.isAlive());
        if (allAliveTargets.length === 0) return; // 敌方全灭,无需攻击
        target = allAliveTargets[Math.floor(Math.random() * allAliveTargets.length)];
    }

    // 执行攻击动作
    if (activeMember.isAlive() && target) {
        activeMember.kick(target);
        console.log(`${activeMember.type} from ${this.name} attacked ${target.type} from ${targetTeam.name}`);
    }
};

3. 关键错误说明

  • 原代码中sameTypeUnit.__proto__(sameTypeUnit)是完全错误的用法,我们改用unit.type === activeMember.type判断同类型——你已经给每个Unit实例设置了type属性,这比检查原型链更直接可靠
  • 原代码遍历成员后只保留最后一个,完全没有意义,我们先正确找到当前要攻击的存活成员
  • 原攻击逻辑混乱,现在拆分成「找攻击方→筛选目标→执行攻击」三个清晰步骤

二、跨原型创建过滤器

跨原型创建过滤器,本质就是根据对象的原型链来筛选实例,这里有几种实用的实现方式:

1. 基于instanceof运算符

instanceof会检查对象的原型链中是否存在构造函数的原型,适合筛选某个构造函数的实例:

// 筛选所有Archer实例
function filterArchers(units) {
    return units.filter(unit => unit instanceof Archer);
}

// 筛选所有Unit的子类实例(包括Archer、Swordsman、Mage)
function filterAllUnits(units) {
    return units.filter(unit => unit instanceof Unit);
}

2. 基于原型对象直接判断

使用Object.prototype.isPrototypeOf方法,检查原型是否在对象的原型链上:

// 筛选所有继承自Unit.prototype的实例
function filterUnitsByPrototype(units) {
    return units.filter(unit => Unit.prototype.isPrototypeOf(unit));
}

// 筛选所有Archer实例
function filterArchersByPrototype(units) {
    return units.filter(unit => Archer.prototype.isPrototypeOf(unit));
}

3. 基于type属性(适配你的场景)

因为你已经给每个Unit子类实例设置了唯一的type属性,直接通过type分组筛选更直观,不需要依赖原型链:

// 通用过滤器:传入要筛选的type
function filterByType(units, targetType) {
    return units.filter(unit => unit.type === targetType);
}

// 使用示例:筛选所有mage类型的实例
const mages = filterByType([archer, swordsman, mage, troll, orc, druid], "mage");

额外优化小建议

  • 原Unit.prototype.kick方法里有个小错误:console.log(this.type + " hit " + this.type);应该打印攻击方和被攻击方的类型,改成console.log(${this.type} hit ${target.type});
  • 在Game.prototype.battle方法中,每次攻击后可以打印双方状态,方便调试:比如console.log(team1.toString()); console.log(team2.toString());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:25:49