使用通过点标记的参数作为函数内的属性访问器

时间:2015-08-28 04:40:49

标签: javascript variables properties brackets

我相当肯定这是一个简单的错误,但我很困惑为什么这不会起作用。我在访问属性时无法找到有关连续使用多个括号的任何文档。这是我的代码的一部分,它创建了一个链接,当点击它时运行" dropItem"功能:

var dropDest = "screwdriver";
var dropCat = "supplies.tools";
dropButton.onclick= function() {dropItem(dropCat, dropDest)};

" dropItem" 功能:

var dropItem = function(category, droppedItem) {
player.inventory[category][droppedItem].amount = player.inventory[category][droppedItem].amount - 1; }; 

我得到一个"无法读取属性'螺丝刀'未定义" 错误。如何正确地通过这个?两个属性都需要是变量才能工作。由于多个括号,这是一个错误吗?

编辑:

我意识到我忘了包含播放器对象的结构,这对于理解为什么我需要传递一个带点标记的类别至关重要:

var player = {
  "health": 100,
  "hydration": 100,
  "hunger": 100,
  "energy": 100,

  "inventory": {
      "supplies": {
          "tools": {
            "screwdriver": {
                "amount": 0,
                "condition": 0
            }
          },
          "buldingMaterials": {
            "wood": {
                "amount": 0,
                "condition": 0
            }
          }
      },          
      "aidPacks": {
          "healthPacks": 0
      }
  }
}

这就是为什么我需要能够使用相同的功能访问player.inventory。 supplies.tools 和player.inventory。 aidPacks.healthpacks

3 个答案:

答案 0 :(得分:1)

在查看了 lightstalker89 的代码后,我意识到我的问题不是括号,而是传递的类别不是在中间解析点符号,因此保持为“耗材” .tools“而不是完全分离。但是,由于播放器对象的结构方式,我需要能够传递点标记类别,所以我拆分字符串:

var player = { "inventory": { "supplies": { "tools" : { "screwdriver" : { "amount" : 1}}}}};
var dropDest = "screwdriver";
var dropCat = "supplies.tools";

function dropItem(category, droppedItem) {
   if(category.indexOf(".") > 0) {
       var newCat = category.split(".");
       var cat1 = newCat[0];
       var cat2 = newCat[1];
       player.inventory[cat1][cat2][droppedItem].amount = player.inventory[cat1][cat2][droppedItem].amount - 1;
       alert(player.inventory[cat1][cat2][droppedItem].amount);
   }else {
       player.inventory[category][droppedItem].amount = player.inventory[category][droppedItem].amount - 1;
       alert(player.inventory[category][droppedItem].amount);
   }
}
dropItem(dropCat, dropDest);

这是JSFiddle:https://jsfiddle.net/j7g0d8kz/

再一次,非常感谢@ lightstalker89让我意识到自己的错误。

答案 1 :(得分:1)

您可以使代码更通用,更简单。当你有两个以上的类别时,这很有用 - 那么你不需要使用[0]和1 - 这里是代码:

var player = { "inventory": { "supplies": { "tools" : { "screwdriver" : { "amount" : 1}}}}};
var dropDest = "screwdriver";
var dropCat = "supplies.tools";

function getProperty(obj, str) {
    return str.split(".").reduce(function(o, x) { return o[x] }, obj);
}

function dropItem(category, droppedItem) {
   var accessString = dropCat + "." + droppedItem;
   getProperty(player.inventory, accessString).amount -= 1;         
   alert(getProperty(player.inventory, accessString).amount);
}
dropItem(dropCat, dropDest);

这是小提琴:https://jsfiddle.net/j7g0d8kz/3/

答案 2 :(得分:0)

你的玩家对象是什么样子的?当您想要更改属性时,它是否为空对象。

基本上你可以像你一样使用多个括号。

如果播放器对象没有所需的属性,那么您的代码应如下所示:

var player = {};
var dropDest = "screwdriver";
var dropCat = "supplies.tools";
function dropItem(category, droppedItem) {
    if(!player.inventory){
        player.inventory = {};
    }
    if(!player.inventory[category]){
        player.inventory[category] = {};
    }
    if(!player.inventory[category][droppedItem]){
       player.inventory[category][droppedItem] = { amount: 0};
    }
    player.inventory[category][droppedItem].amount = player.inventory[category][droppedItem].amount - 1;       
}
dropItem(dropCat, dropDest);
alert(JSON.stringify(player));
alert(player.inventory[dropCat][dropDest].amount);

这是小提琴:https://jsfiddle.net/csqbjnd7/1/

如果玩家对象存在,您可以使用多个括号。代码应如下所示:

var player = { "inventory": { "supplies.tools" : { "screwdriver" : { "amount" : 1}}}};
var dropDest = "screwdriver";
var dropCat = "supplies.tools";
function dropItem(category, droppedItem) {
   player.inventory[category][droppedItem].amount = player.inventory[category][droppedItem].amount - 1;
}
dropItem(dropCat, dropDest);
alert(player.inventory[dropCat][dropDest].amount);
alert(JSON.stringify(player));

这是小提琴:https://jsfiddle.net/9o1949oz/2/