在函数中使用传递的点标记参数作为 属性 访问器

Using a Passed Dot-Notated Parameter as Property Accessor within a Function

我相当确定这是一个简单的错误,但我很困惑为什么这不起作用。在访问属性时,我一直无法找到有关在一行中使用多个括号的任何文档。这是我的代码的一部分,它创建了一个 link,当点击时运行 "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; }; 

我收到 "Cannot read property 'screwdriver' of undefined" 错误。如何正确地通过这个?这两个属性都需要是变量才能工作。这是由于多个括号导致的错误吗?

编辑:

我意识到我忘了包括播放器对象的结构,这对于理解为什么我需要通过点标记类别很重要:

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.[ 的原因=44=] 功能相同。

你的玩家对象是什么样子的?想改属性的时候是不是空对象

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

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

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);

这里是fiddle: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));

这里是fiddle:https://jsfiddle.net/9o1949oz/2/

看了 lightstalker89 的代码后,我意识到我的问题不是括号,而是传递的类别没有解析中间的点符号,因此保持 "supplies.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 让我意识到我的错误。

您可以使您的代码更通用、更简单。当您有两个以上的类别时,这很有用 - 然后您不需要使用 [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);

这是fiddle:https://jsfiddle.net/j7g0d8kz/3/