如何在 javascript 中创建具有不同变量的可重用函数

How to create a reusable function with different variables in javascript

我正在使用 javascript/html 开发游戏。我有很多按钮,它们都使用相同的功能,但它们内部的值不同。

我有 32 个按钮,这意味着 32 个功能,这些功能完全相同,只是它们使用不同的 variables/values。

我正在考虑使用 objects/arrays,并将一个函数放入一个对象中,然后重新使用它来更改其变量,但我不知道这是否可行,或者这是否是个好主意。

我对此还是个新手。这些按钮用于 "attack" 怪物,每个按钮都是不同的,即 "stats/health/damage"。

我的按钮名为 "attack1/attack2/",功能为 "attack1/attack2"。每次我想添加一个怪物时,我都会复制整个函数并更改它的值,这并不难,但考虑到我想更改伤害公式,我需要更改所有 32 个函数,这不是我想要做的。

我已经创建了一个对象,我使用数组在其中存储所有怪物数据。

最后,我的母语不是英语,如果您听不懂我的意思,请见谅。如果有任何方法可以帮助您更好地理解它,请告诉我。

谢谢

var monsterStats = {
killed: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

hp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200, 2600,
3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000, 40000,
48000, 570000, 65000, 72000, 80000, 88000],

maxHp: [10, 30, 70, 130, 190, 280, 380, 500, 700, 900, 1300, 1600, 2200,
2600, 3000, 4000, 5000, 7000, 9000, 12000, 15000, 18000, 22000, 28000, 34000,
40000, 48000, 570000, 65000, 72000, 80000, 88000],

def: [0, 2, 4, 6, 9, 13, 18, 25, 30, 38, 45, 53, 65, 75, 88, 95, 120, 140,
170, 200, 220, 250, 300, 400, 500, 700, 1000, 1200, 2000, 2500, 3000],

minDmg: [2, 2, 4, 6, 9, 13, 18, 25, 32, 40, 50, 60, 75, 86, 96, 105, 140,
160, 200, 230, 260, 290, 350, 420, 500, 900, 1200, 1700, 2500, 3200, 4500,
6000],

maxDmg: [3, 5, 7, 10, 14, 19, 23, 30, 37, 45, 58, 67, 80, 92, 100, 110,
160, 185, 215, 250, 275, 320, 380, 550, 700, 1200, 1500, 2200, 3000, 4000,
5500, 8000],

baseExp:[5, 10, 30, 50, 90, 140, 190, 260, 340, 450, 560, 700, 810, 940,
1060, 1200, 1600, 2150, 2600, 3400, 5000, 7000, 10000, 15000, 23000, 35000,
70000, 120000, 180000, 290000, 430000, 680000, 1000000]

};

function attack(number) {
if (monsterStats.hp[0] >= 1) {
    var damage = Math.floor(Math.random() * (maxdamage - mindamage + 1)) +
        mindamage;
    damage = Math.floor(damage - monsterStats.def[0] * 1.2);
    if (damage > 1) {
        monsterStats.hp[0] -= damage;
        document.getElementById("hp1").innerHTML = monsterStats.hp[0];
        Log("You deal " + damage + " <span style=\"color:blue\">damage</span>");
    } else Log("<span style=\"color:blue\">Enemy block your attack! </span>");
    var dmg = Math.floor(Math.random() * (monsterStats.maxDmg[0] - monsterStats.minDmg[0] + 1)) + monsterStats.minDmg[0];
    dmg = Math.floor(dmg - defense * 1.2);
    if (dmg > 1) {
        health = health - dmg;
        document.getElementById("health").innerHTML = health;
        Log("Enemy hit you for " + dmg + " <span style=\"color:red\">damage</span>");
    } else Log("<span style=\"color:green\">You blocked enemy attack! </span>");
    if (health < 1) {
        monsterStats.hp[0] = monsterStats.maxHp[0];
        health = maxhealth;
        document.getElementById("hp1").innerHTML = monsterStats.hp[0];
        document.getElementById("health").innerHTML = health;
        Log("<span style=\"color:blue\">You have lost!</span>");
    }
    if (monsterStats.hp[0] < 1) {
        monsterStats.killed[0] = monsterStats.killed[0] + 1;
        monsterStats.hp[0] = monsterStats.maxHp[0];
        document.getElementById("hp1").innerHTML = monsterStats.hp[0];
        document.getElementById("kills1").innerHTML = monsterStats.killed[0];
        var expgain = monsterStats.baseExp[0] / (level / 5);
        if (experience < maxexperience) {
            experience = Math.floor(experience + expgain);
            if (experience >= maxexperience) {
                level += 1;
                stats += 2;
                experience = experience - maxexperience;
                maxexperience = Math.floor(maxexperience * 1.2);
                Log("You leveled up! Your current level is: " + level);
                document.getElementById("maxexperience").innerHTML = maxexperience;
                document.getElementById("level").innerHTML = level;
                document.getElementById("stats").innerHTML = stats;
                document.getElementById("experience").innerHTML = experience;
            } else Log("You gain: " + Math.floor(expgain) + "experience!");
            document.getElementById("experience").innerHTML = experience;
        }
        var goldLog = 0;
        var golddrop = Math.floor((Math.random() * 100) + 1);
        if (golddrop > 95) {
            golddrop = Math.floor((Math.random() * 20) + 1);
            gold = gold + golddrop;
            Log("You loot: " + golddrop + "gold!");
            document.getElementById("gold").innerHTML = gold;
        } else if (golddrop >= 75) {
            golddrop = Math.floor((Math.random() * 10) + 1);
            gold = gold + golddrop;
            Log("You loot: " + golddrop + "gold!");
            document.getElementById("gold").innerHTML = gold;
        } else if (golddrop >= 60) {
            golddrop = Math.floor((Math.random() * 5) + 1);
            gold = gold + golddrop;
            Log("You loot: " + golddrop + "gold!");
            document.getElementById("gold").innerHTML = gold;
        }
        "This is <span style=\"color:red\">RED</span> text.";
        var itemdrop = Math.floor((Math.random() * 100) + 1);
        if (itemdrop < 33) {
            var fusiondrop = Math.floor((Math.random() * 100) + 1);
            if (fusiondrop < 70) {
                common = common + 1;
                Log("You loot:<span style=\"color:grey\">Common</span> Fusion stone!");
                document.getElementById("common").innerHTML = common;
            } else if (fusiondrop <= 100) {
                rare = rare + 1;
                Log("You loot:<span style=\"color:blue\">Rare</span> Fusion stone!");
                document.getElementById("rare").innerHTML = rare;
            }
        } else if (itemdrop < 66) {
            var expdrop = Math.floor((Math.random() * 100) + 1);
            if (expdrop < 70) {
                commonexp = commonexp + 1;
                Log("You loot:<span style=\"color:grey\">Common</span> Exp orb!");
                document.getElementById("commonexp").innerHTML = commonexp;
            } else if (expdrop <= 100) {
                rareexp = rareexp + 1;
                Log("You loot:<span style=\"color:blue\">Rare</span> Exp orb!");
                document.getElementById("rareexp").innerHTML = rareexp;
            }
        } else {
            var golddrop = Math.floor((Math.random() * 100) + 1);
            if (golddrop < 70) {
                commongold = commongold + 1;
                Log("You loot:<span style=\"color:grey\">Common</span> Gold orb!");
                document.getElementById("commongold").innerHTML = commongold;
            } else if (golddrop <= 100) {
                raregold = raregold + 1;
                Log("You loot:<span style=\"color:blue\">Rare</span> Gold orb!");
                document.getElementById("raregold").innerHTML = raregold;
            }
        }
    }
}

}

那是代码的一部分,我使用这段代码 32 次。

假设您创建一个 Monster "objects" 的数组,如下所示:

var Monsters = {
    "foo": {"name":"Foo the foot", "hp":125, "power":3},
    "bar": {"name":"Barbarian the bar", "hp":25, "power":9001}
};

您也可以编写按钮标记,这样每个按钮都可以与一个怪物相关联。例如:

<button rel="attack" data-monster_id="foo">Attack</button>
<button rel="attack" data-monster_id="bar">Attack</button>

现在,您可以 link 他们这样说:

var btns = document.querySelectorAll('button[rel="attack"]');
for (var i=0; i<btns.length; i++) {
    this.addEventListener('click', function(){
        attack(this.dataset.monster_id);
    }, false);
}

最后,假设一个 attack 方法是这样的:

function attack(id) {
    Monsters[id].hp -= currentDamage;
    // whatever consequences the attack may have
}

希望这能给您带来灵感,祝您游戏顺利:)

不确定您的意思,但我认为使用 event delegation 可能有助于重用函数。在代码片段示例中,data-* 属性用于存储带有按钮的分数。此外,事件委托使您能够创建新按钮而无需分配新的处理程序。

document.querySelector('#testbuttons').addEventListener('click', testdemo);
document.querySelector('#testcreate').addEventListener('click', newbttn);

// handler for all buttons within div#testbutton
function testdemo(e) {
  var from = e.target || e.srcElement
     ,score = from.getAttribute('data-score')
     ,kills = JSON.parse(from.getAttribute('data-kills'));
  if (!score) { return true; }
  Helpers.log2Screen('score clicked button: ', score, 
                     ', kills: <code>[', kills, ']</code>',
                      {clear: true});
}

function newbttn() {
  var score = Math.floor(1+Math.random()*200);
  document.querySelector('#testbuttons').innerHTML +=
    '<br><button data-score="'+score+'" data-kills="[]">button '+score+'</button>';
  Helpers.log2Screen('Created new button with score ', score, {clear: true});
}
button {
  margin-top: 3px;
}
<!-- a few helpers -->
<script src="http://kooiinc.github.io/JSHelpers/Helpers-min.js"></script>

<div id="result"><p>Awaiting action ...</p></div>
<div id="testbuttons">
  <button data-score="12" data-kills="[2,5,3]">bttn 12</button><br>
  <button data-score="122" data-kills="[0,2,8]">bttn 122</button>
</div>

<button id="testcreate">create new button</button>

我想你正在寻找这样的东西:

function createAttack1(damage) {
    return function() {
        ... Your attack1 logic using 'damage'
    }
}

然后你可以用它来连接你的按钮:

button1.addEventListener("click", createAttack1(5));
button2.addEventListener("click", createAttack1(10));
button3.addEventListener("click", createAttack1(15));

这允许您重复使用相同的核心逻辑,同时拥有不同的统计数据,而不需要您一直在做的所有 copy/paste。