根据对象属性修改全局变量

4

我是一个有用的助手,将为您进行文本翻译。

我正在尝试学习面向对象的JavaScript,并遇到了以下问题:

我有一个像这样的对象构造器(是否是正确的术语?):

function itemCreator(itemName, itemType, itemPositionX, itemPositionY) {
            this.itemName = itemName;
            this.itemType = itemType;
            this.itemPositionX = itemPositionX;
            this.itemPositionY = itemPositionY;
            allItems.push(this); //store all items in a global variable
            }//end itemCreator;


//then I use it to create an object

megaRocket = new itemCreator (
           'megarocket',
           'item_megarocket',
           108,
           475
           )

现在我意识到我还需要将这些对象映射到不同的全局变量以修改,基于对象的 "itemType" 属性。但是我卡住了。如何创建一个只有特定 itemType 属性的对象才能修改的全局变量?

例如,我想创建一个对象来增加名为 amountOfMegarockets 的变量,但仅当该对象的 itemType 为 "item_megarocket" 时。

我稍后计划循环这些项的数组,看看玩家对象是否接触它们(以收集该项):

function checkForItems(){ 
                var itemLen =allItems.length;
                for (i=0; i < itemLen; i++){
                var itemObject = allItems[i];

                if ( //checking for "collisions" here
                (ship.x < (itemObject.itemBitmap.x + itemObject.size) &&  (ship.x + shipWidth) > itemObject.itemBitmap.x) &&
                (ship.y < (itemObject.itemBitmap.y + itemObject.size) &&  (ship.y + shipWidth) > itemObject.itemBitmap.y)
                ){
                itemObject.actor.y = -500; //just removing the item from canvas here (temporary solution)
                // Here comes pseudo code for the part that I'm stuck with  
                variableBasedOnItemObject.itemType++;

                }

我希望我的解释对某个人有意义!
编辑:
Bergi的回答对我来说最有意义,但我无法正确使用语法。这是我正在尝试使用Bergi代码的方式:
var amounts = {},
allItems = [];
function itemCreator(itemName, itemType, itemPositionX, itemPositionY) {
this.itemName = itemName;
this.itemType = itemType;
this.itemPositionX = itemPositionX;
this.itemPositionY = itemPositionY;

(amounts[itemType]=2); // this is different from bergi's example because I need to set the initial value of the item to two
//I also shouldn't increase the item amount on creation of the item, but only when it's specifically called from another function
this.increaseCount = amounts[itemType]++; //this should IMO increase the itemType amount inside the amounts object when called, but it doesn't seem to work
}

//creating the object the way bergi suggested:
allItems.push(new itemCreator('shootUp001', 'item_up', 108, 475)); 

现在,这里有个问题部分:
function checkForItems(){ 
                var itemLen =allItems.length;
                for (i=0; i < itemLen; i++){
                var itemObject = allItems[i];

                if ( my condition here)
                ){

//code below is not increasing the value for the current itemType in the amounts object. 
//Probably a simple syntax mistake?
                itemObject.itemType.increaseCount; 

                }

           }

           }

为什么我的itemObject.itemType.increaseCount的调用没有增加amounts.itemType的值?

1
在我看来,这根本不是正确的方法。你应该将逻辑分成不同的类,而不是放在一个庞大的类下面。 - user1508519
在我看来,这不是一个单体类,因为所有的“项”非常相似并且共享相同的属性。不同项之间唯一的主要区别应该是它们影响的计数器变量。 - Sony packman
2
任何以“修改全局变量”开头的问题都已经问错了。 - Ingo Bürk
@IngoBürk 加100分! - Alnitak
@IngoBürk 好的,那么如果几个不同的函数需要读取同一个变量,我该如何处理这种情况? - Sony packman
有很多方法。您可以传递变量(或包含变量的对象)。您也可以使用您使用的模式,但应该在自己的本地范围内执行,而不是在全局范围内执行。一个非常简单的方法是使用自调用函数来创建本地范围。 - Ingo Bürk
2个回答

1
增加一个名为amountOfMegarockets的全局变量,但仅当该对象的itemType为“item_megarocket”时。不要为每种物品类型使用全局变量。使用一个对象(在全局或本地范围内),该对象在其属性上计算每种类型的数量。
var amounts = {},
    allItems = [];
function Item(itemName, itemType, itemPositionX, itemPositionY) {
    this.itemName = itemName;
    this.itemType = itemType;
    this.itemPositionX = itemPositionX;
    this.itemPositionY = itemPositionY;

    amounts[itemType]++ || (amounts[itemType]=1); // count by type
    allItems.push(this); // store all items
}

请注意,我不会默认将所有Item实例放入数组中,最好省略那一行并让调用者处理:
allItems.push(new Item('megarocket', 'item_megarocket', 108, 475));

我感觉我快要成功了,但似乎找不到修改“amount”对象的正确语法。我将编辑我的问题以更好地展示我如何尝试使用您的解决方案(但没有成功)! - Sony packman
哎呀,现在我的头真的很疼:我们在构造函数中几乎以相同的方式使用itemType,你是不是在说我的旧代码?我在我的问题下面编辑了一个新版本的代码,并包含了你的建议。 - Sony packman
我指的是你在checkForItems中的代码,在其中一个Item构造函数中,你正确地使用了括号表示法。但是你似乎每次调用构造函数时都要初始化(重置)数量为2 - 这就是为什么我使用了一个条件语句(它隐藏在OR表达式中)。 - Bergi
好的,现在我开始理解了!我会快速测试一些内容,然后接受你的答案。 - Sony packman
我认为你现在正在寻找 amounts[itemObject.itemType]++ (假设 amounts 对象已经被正确初始化,比如 var amounts = {"item_megarocket": 0, …};)。 - Bergi
显示剩余3条评论

0

你可以做一些像这样的事情

(function (global) {
    // create a scope
    var allItems = [];
    global.itemCreator = function(itemName, itemType, itemPositionX, itemPositionY) {
        this.itemName = itemName;
        this.itemType = itemType;
        this.itemPositionX = itemPositionX;
        this.itemPositionY = itemPositionY;
        allItems.push(this); //store all items in a global variable
        }//end itemCreator;
})(this);

这会起作用。但是真的不要过于复杂化你的代码,只是为了创建私有变量。如果有人想使用调试器欺骗,他总能找到方法来做。

---- 编辑 如果你只想基于 itemType 访问全局变量,可以做一些像这样的事情:

function checkForItems(){ 
    var itemLen =allItems.length;
    for (i=0; i < itemLen; i++){
        var itemObject = allItems[i];

        if ( //checking for "collisions" here
            (ship.x < (itemObject.itemBitmap.x + itemObject.size) &&  (ship.x + shipWidth) > itemObject.itemBitmap.x) &&
            (ship.y < (itemObject.itemBitmap.y + itemObject.size) &&  (ship.y + shipWidth) > itemObject.itemBitmap.y)
        ){
            itemObject.actor.y = -500; //just removing the item from canvas here (temporary solution)
            // Here comes pseudo code for the part that I'm stuck with  
            if (window[itemObject.itemType + "Data"])) {
                variableBasedOnItemObject.itemType++;
            } else {
                window[itemObject.itemType + "Data"] = {
                    itemType: 1
                }
            }
        }
    }
}

我不确定我理解这个答案。假设有一个名为“amountOfMegarockets”的全局变量。如何编写一个函数,仅在“this”具有megaRocket项目类型时修改该变量? - Sony packman
好的。抱歉,我没有理解你的问题。你可以使用字符串来访问变量,例如:window["amountOf" + this.itemType + "s"].push(this)。但要注意复数形式和对象是否存在(例如:window.hasOwnProperty("amountOf" + this.itemType + "s"))。 - peernohell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接