我的代码由于某种原因显示NaN而不是数字

时间:2017-11-28 15:42:29

标签: javascript

单击NaN按钮时,为什么我会收到#plr1button1而不是数字? 就像我不理解它我看了2个小时,我仍然无法弄清楚错误。

class Fighter {
    constructor(atk, def, hp) {
        this.atk = atk;
        this.def = def;
        this.hp = hp;
    }
}
var Fighter1 = new Fighter(40, 5, 100);
var Fighter2 = new Fighter(30, 20, 100);
Fighter1.attack = function() {
    var attack1 = this.atk + (Math.floor(Math.random() * 5) - 5) - Fighter2.def;
    Fighter2.hp = Fighter2.hp - attack1;
    document.getElementById("hp2").innerHTML = Fighter2.hp;
}
Fighter2.attack = function() {
    var attack1 = this.atk + (Math.floor(Math.random() * 5) - 5) - Fighter1.def;
    Fighter1.hp = Fighter1.hp - attack1;
    document.getElementById("hp1").innerHTML = Fighter1.hp;
}
function random() {
    var randomNum =  Math.floor(Math.random() * 6) + 1;
    /*var randomNum2 =  Math.floor(Math.random() * 6) + 1;
    var randomNum3 =  Math.floor(Math.random() * 6) + 1;*/
    if (randomNum === 1) {
        document.getElementById("plr1button1").innerHTML = "Attack";
        $("#plr1button1").bind("click", Fighter1.attack);
        document.getElementById("plr2button1").innerHTML = "Attack";
    }
}

2 个答案:

答案 0 :(得分:3)

您丢失了该事件处理程序的上下文;使用.bind来修复它。

$("#plr1button1").bind("click", Fighter1.attack.bind(Fighter1));

很容易检测到它:只需将断点放入attack方法,然后检查this等于何时调用方法click事件处理程序。

您的代码还有其他几个问题。

首先,您可以轻松地抽象一个在给定范围内生成随机整数的函数 - 并重复使用它而不是重复整个Math.floor(Math.random...代码段。

其次,你在attack代码中混合了两个问题,改变了状态(受攻击的战斗机)及其表示。分开这些通常会更好。

最后,您不必要地硬编码了两个Fighter实例中的所有操作 - 而不是使用prototype来存储单个函数。

例如,有一种方法可以简化:

class Fighter {
    constructor(atk, def, hp) {
        this.atk = atk;
        this.def = def;
        this.hp = hp;
    }

    attack(enemy) {
        const hits = this.atk + _randomInRange(0, 5) - enemy.def;
        enemy.hp -= hits;
        enemy.render();
    }

    render() {
        // updates the representation of Fighter
    }
}

function _randomInRange(from, to) {
  return from + Math.floor( Math.random() * (to + 1 - from) );
}

此处采用small (and incomplete) demo方法。

答案 1 :(得分:1)

这是因为你如何称呼它,this不是Fighter1,它是触发事件的元素(因为你正在使用jQuery; vanilla) JS它将是Fighter1.attack内的事件对象。

当您直接调用某个功能时,它会使用该功能,但不会维护它的常用环境。即,回调中的Fighter1.attackFighter1.attack()不同。

您需要做的是将函数绑定到各自的this,以便将它们保留在内部。

更改您的回调:

$("#plr1button1").bind("click", Fighter1.attack.bind(Fighter1));

然后,当它被触发时,this将按照您的意图Fighter1

您还可以将整个函数绑定到不必重新绑定:

Fighter1.attack = (function() {
    var attack1 = this.atk + (Math.floor(Math.random() * 5) - 5) - Fighter2.def;
    Fighter2.hp = Fighter2.hp - attack1;
    document.getElementById("hp2").innerHTML = Fighter2.hp;
}).bind(Fighter1);

重复Fighter2