【问题标题】:The object referred to by string isn't being displayed字符串引用的对象未显示
【发布时间】:2018-02-07 22:04:47
【问题描述】:

我的意图:使用对象制作 CYOA

我是 Javascript 的新手,一直在尝试制作一个简单的 CYOA 游戏,使用来自 this Reddit commentthis code 作为模板。但是,我想使用对象(其值应该是常量)来存储消息的各种字符串值和每个选择指向的对象,而不是将所有对象都放在数组中并且必须使用 using 指向它们他们在数组中的索引。我的理由是(理论上)我使用“msg_001”或“story5_28”之类的字符串组织起来会更简单,而不是在我在中间插入一些新消息时更改一堆数字数组。

我的问题:第一条消息不再显示

基本上,我想循环回到第一条消息及其答案集,但它不会。

初始printCurrentMsg() 起作用(将“消息”div 的内容更改为msgText 的值,并循环遍历对象的choices 数组以设置“选择”div 中的按钮,基于currentMsg) 中指定的对象和按钮各自的 onlick 属性似乎可以工作,直到它们被设置为显示 msg_000

似乎无论currentMsg 的值是什么,printCurrentMsg 都不会显示字符串所指的对象,除非它最初显示。此外,在脚本中的各个点使用console.log 之后,我注意到currentMsg 没有改变,并且对currentMsgwindow[currentMsg] 都使用console.log(typeof) 表明前者是一个字符串,而后者是一个东西。我是否无意中创建了两个单独的变量?

我试过了……

  • ...使用printCurrentMessage中的参数。
  • ...在函数中使用currentMsg 而不是window[currentMsg]
  • ...使用点表示法而不是括号表示法。
  • ...使用this[] 而不是window[]

我不确定这是否与asynchronicity 有关,我是accessing object properties 不正确,我对scope 的理解有缺陷,或者我是否错误地使用了全局变量。我应该使用某种回调吗?

使用“虚拟”msg_000——制作另一个名称不同但属性相同的对象——作为权宜之计,但我仍然不明白问题出在哪里。将所有msg_*** 对象放在一个数组中并通过索引号而不是字符串来引用它们也可以,但我很犹豫是否要依赖它来解决上述乏味和我仍然不明白为什么currentMsg 的值保持不变。

为了更好地表达我的问题,here is a jsfiddle with my code,我也将其发布在下面。

//messages
var msg_000 = { //Starts with this one, I want to be able to go back to it
  msgName: "msg_000",
  msgText: "Sup! Choose an option!",
  choices: [
    ans_000 = {
      ansText: "Climb a hill!",
      ansGoto: "msg_001" //this works
    },
    ans_001 = {
      ansText: "Skin a cat!",
      ansGoto: "msg_002" //this works
    },
    ans_002 = {
      ansText: "Build a birdhouse!",
      ansGoto: "msg_003" //this works
    }
  ]
};
var msg_001 = {
  msgName: "msg_001",
  msgText: "You summit the great snowy peaks!",
  choices: [
    ans_000 = {
      ansText: "Talk to the Recursion Guru!",
      ansGoto: "msg_000" //this doesn't work
    }
  ]
};
var msg_002 = {
  msgName: "msg_002",
  msgText: "You suffer severe lacerations to the face!",
  choices: [
    ans_000 = {
      ansText: "Start Over",
      ansGoto: "msg_000" //this doesn't work
    }
  ]
};
var msg_003 = {
  msgText: "You build a pretty average looking birdhouse. Some grackles have moved in nonetheless, placing their various knicknacks, bedding materials, and chrono-gateways within their new abode.",
  choices: [
    ans_000 = {
      ansText: "Step through the chrono-gateway!",
      ansGoto: "msg_000" //this doesn't work
    },
    ans_001 = {
      ansText: "I think I wanna climb that mountain over there.",
      ansGoto: "msg_001" //this works
    }
  ]
}

var currentMsg = "msg_000"; //the first message is "msg_000"

printCurrentMsg = function() {
  document.getElementById("message").innerHTML =
    window[currentMsg].msgText;
  //sets the message (the div with the id of "message")
  //based on the "currentMsg" variable. "currentMsg.msgText" 
  //doesn't seem to work.
  var choices = "";
  for (var i = 0, l = window[currentMsg].choices.length; i < l; i++) {
    choices += "<p><button onclick='setMessage(" +
      window[currentMsg].choices[i].ansGoto + ")'>" +
      window[currentMsg].choices[i].ansText + "<br>Goto " +
      window[currentMsg].choices[i].ansGoto + "</button></p>";
    //make the buttons, sets the button's onclick 
    //"setMessage" function's parameter to the the value of 
    //the "ansGoto" property -> in the answers object at the 
    //i/th index of the choices property array -> in the 
    //"msg_(number)" object."
  };
  document.getElementById("choices").innerHTML = choices;
  //takes the value of the "choices" [local?] variable and puts 
  //it in the "choices" div.
};

setMessage = function(msg) {
  window[currentMsg] = msg; //I think this is the source of all 
  //my problems, it's supposed to set "currentMsg" to the value 
  //of the "msg" parameter, but when I check it with 
  //console.log(currentMsg) it hasn't been changed (i.e., still 
  //it's initial value of "msg_000") and when I use 
  //console.log(window[currentMsg]) it returns "[Object 
  //object]"; using typeof shows me that "currentMsg" is a 
  //string and "window[currentMsg]" is an object. I thought 
  //they both were the same object, am I unintentionally 
  //creating two different objects?
  printCurrentMsg(); //runs that function, seems to display the 
  //messages except the ones from object "msg_000".
};

printCurrentMsg(); //Displays the initial message and choices 
//from "msg_000", but after a new message is chosen it won't 
//display "msg_000" if it's pointed to from an "ansGoto" 
//property.
<!DOCTYPE html>
<html>

<body>

  <div id="message"></div>
  <!-- "msgText" goes here -->
  <div id="choices"></div>
  <!-- "choices" go here -->

</body>

</html>

感谢您的宝贵时间。

【问题讨论】:

  • 我希望我的问题标题不要太含糊;我不确定如何简洁地表达我的问题这一事实可能说明了我的问题的性质。
  • 不要使用动态变量名,使用对象来保存所有消息。

标签: javascript html object scope global-variables


【解决方案1】:

setMessage() 执行window[currentMsg] = msg; 时,它会替换保存消息的变量的值。例如。如果当前消息是msg_000,而你是setMessage(msg_002),则相当于写msg_000 = msg_002;

您真正想要做的是将currentMsg 的值更改为新消息的名称。所以你应该这样做:currentMsg = msg.msgName;

您还缺少msg_003 中的msgName 属性。

作为最佳实践,您不应该对所有这些都使用全局变量。创建您自己的对象messages,并使用messages[currentMsg]

//messages
var msg_000 = { //Starts with this one, I want to be able to go back to it
  msgName: "msg_000",
  msgText: "Sup! Choose an option!",
  choices: [
    ans_000 = {
      ansText: "Climb a hill!",
      ansGoto: "msg_001" //this works
    },
    ans_001 = {
      ansText: "Skin a cat!",
      ansGoto: "msg_002" //this works
    },
    ans_002 = {
      ansText: "Build a birdhouse!",
      ansGoto: "msg_003" //this works
    }
  ]
};
var msg_001 = {
  msgName: "msg_001",
  msgText: "You summit the great snowy peaks!",
  choices: [
    ans_000 = {
      ansText: "Talk to the Recursion Guru!",
      ansGoto: "msg_000" //this doesn't work
    }
  ]
};
var msg_002 = {
  msgName: "msg_002",
  msgText: "You suffer severe lacerations to the face!",
  choices: [
    ans_000 = {
      ansText: "Start Over",
      ansGoto: "msg_000" //this doesn't work
    }
  ]
};
var msg_003 = {
  msgName: "msg_003",
  msgText: "You build a pretty average looking birdhouse. Some grackles have moved in nonetheless, placing their various knicknacks, bedding materials, and chrono-gateways within their new abode.",
  choices: [
    ans_000 = {
      ansText: "Step through the chrono-gateway!",
      ansGoto: "msg_000" //this doesn't work
    },
    ans_001 = {
      ansText: "I think I wanna climb that mountain over there.",
      ansGoto: "msg_001" //this works
    }
  ]
}

var currentMsg = "msg_000"; //the first message is "msg_000"

printCurrentMsg = function() {
  document.getElementById("message").innerHTML =
    window[currentMsg].msgText;
  //sets the message (the div with the id of "message")
  //based on the "currentMsg" variable. "currentMsg.msgText" 
  //doesn't seem to work.
  var choices = "";
  for (var i = 0, l = window[currentMsg].choices.length; i < l; i++) {
    choices += "<p><button onclick='setMessage(" +
      window[currentMsg].choices[i].ansGoto + ")'>" +
      window[currentMsg].choices[i].ansText + "<br>Goto " +
      window[currentMsg].choices[i].ansGoto + "</button></p>";
    //make the buttons, sets the button's onclick 
    //"setMessage" function's parameter to the the value of 
    //the "ansGoto" property -> in the answers object at the 
    //i/th index of the choices property array -> in the 
    //"msg_(number)" object."
  };
  document.getElementById("choices").innerHTML = choices;
  //takes the value of the "choices" [local?] variable and puts 
  //it in the "choices" div.
};

setMessage = function(msg) {
  currentMsg = msg.msgName;
  printCurrentMsg(); //runs that function, seems to display the 
  //messages except the ones from object "msg_000".
};

printCurrentMsg(); //Displays the initial message and choices 
//from "msg_000", but after a new message is chosen it won't 
//display "msg_000" if it's pointed to from an "ansGoto" 
//property.
<!DOCTYPE html>
<html>

<body>

  <div id="message"></div>
  <!-- "msgText" goes here -->
  <div id="choices"></div>
  <!-- "choices" go here -->

</body>

</html>

【讨论】:

  • 这太好了,谢谢。我以为我的错误在于使用window[currentMsg]。缺少的msgName 源于早期尝试使用属性找到解决方案(显然我应该从那个角度继续尝试)。我试图清除示例的所有无关代码,我猜我错过了前四个对象中的 msgName 属性。我做得很好!
猜你喜欢
  • 2012-05-31
  • 2013-03-24
  • 2011-08-06
  • 2013-07-03
  • 1970-01-01
  • 2015-10-04
  • 2021-10-24
  • 1970-01-01
  • 2010-11-12
相关资源
最近更新 更多