【问题标题】:How to obtain a var inside a function in another function?如何在另一个函数中获取函数内部的var?
【发布时间】:2020-12-17 17:43:51
【问题描述】:

在我的游戏中,玩家可以选择掷 2、3 或 4 个骰子,然后选择所选择的号码。骰子将被滚动并且最大的数字获胜。但是,当用户选择要滚动的 3 或 4 个骰子时,我无法在按下提交按钮时触发的事件侦听器中获取 var randomNumber1 - var randomNumber4。我需要那些var 来继续编码。谁能帮忙谢谢。

在我的最后 4 行 javascript 代码中,if (noOfChoices === "3")console.log(userChoices); 没有打印,即使上面的 if (noOfChoices === "2") 的情况有效。 chrome开发工具上显示的错误信息是:

index.js:91 Uncaught ReferenceError: randomNumber1 is not defined
    at HTMLAnchorElement.<anonymous> (index.js:91)

谁能帮忙谢谢。

这是我的 javascript 代码:

function diceRoll() {
  var randomNumber1 = Math.floor(Math.random() * 6 + 1);
  var Image1 = "dice" + randomNumber1 + ".png";
  document.querySelectorAll("img")[1].setAttribute("src", Image1);

  var randomNumber2 = Math.floor(Math.random() * 6 + 1);
  var Image2 = "dice" + randomNumber2 + ".png";
  document.querySelectorAll("img")[2].setAttribute("src", Image2);

  var randomNumber3 = Math.floor(Math.random() * 6 + 1);
  var Image3 = "dice" + randomNumber3 + ".png";
  document.querySelectorAll("img")[3].setAttribute("src", Image3);

  var randomNumber3 = Math.floor(Math.random() * 6 + 1);
  var Image4 = "dice" + randomNumber4 + ".png";
  document.querySelectorAll("img")[4].setAttribute("src", Image4);
}

// Storing user noOfChoices
let links = document.querySelectorAll('#list li')
links.forEach((el) => {
  el.addEventListener('click', (event) => {
    let numberOfChoices = event.target.innerText
    document.getElementById('dropdownMenu').innerHTML = `${numberOfChoices}<span class="caret"></span>`)})

// Responding to Submit
document.getElementById("submit").addEventListener("click", function(e) {
  e.preventDefault();

// Storing Data into variables
  var choice1 = $("#choice1").val();
  var choice2 = $("#choice2").val();
  var choice3 = $("#choice3").val();
  var choice4 = $("#choice4").val();
  var noOfChoices = $("#dropdownMenu").text();
  var userChoices = [];

// Displaying no. of dices that user chose
    if (noOfChoices === "2") {
      $("#caption1, #caption2").removeClass("invisible");
      $("#caption3, #caption4").addClass("invisible");
    }

    if (noOfChoices === "3") {
      $("#caption1, #caption2, #caption3").removeClass("invisible");
      $("#caption4").addClass("invisible");
    }

    if (noOfChoices === "4") {
      $(".caption").removeClass("invisible");
    }

$("#submit").html("Again");

// Rolling Dice
diceRoll();

// Determining Winner
if (noOfChoices === "2") {if (randomNumber1 > randomNumber2) {$("#title").html(choice1 + " wins! ????");}
else if (randomNumber2 > randomNumber1) {$("#title").html(choice2 + " wins! ????");}
else if (randomNumber2 = randomNumber1){$("#title").html("Oops, try again!");}
}

if (noOfChoices === "3") {userChoices.push(randomNumber1, randomNumber2,randomNumber3);
console.log(userChoices);
}
})}

这是我的html:

<head>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</head>

<body>
<div class="container-of-images">
      <img src="chick2.png">

      <figure>
        <img id="img1" class="dice" src="dice6.png">
        <figcaption class="caption" id="caption1">Choice 1</figcaption>
      </figure>

      <figure>
        <img id="img2" class="dice" src="dice6.png">
        <figcaption class="caption" id="caption2">Choice 2</figcaption>
      </figure>

      <figure class="threeChoices">
        <img id="img3" class="dice" src="dice6.png">
        <figcaption class="caption" id="caption3">Choice 3</figcaption>
      </figure>

      <figure class="fourChoices">
        <img id="img4" class="dice" src="dice6.png">
        <figcaption class="caption" id="caption4">Choice 4</figcaption>
      </figure>
      <img src="chick1.png">
    </div>

  <div class="container-of-forms">

    <!-- Dropdown Button -->
    <div class="dropdown">
      <button class="btn btn-info dropdown-toggle" type="button" id="dropdownMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
        0
        <span class="caret"></span>
      </button>
      <ul id="list" class="dropdown-menu dropdown-info" aria-labelledby="dropdownMenu">
        <li><a href="#">2</a></li>
        <li><a href="#">3</a></li>
        <li><a href="#">4</a></li>
      </ul>

      <!-- Input Text Fields -->
      <div class="container-inner">  <br>
        <input class="text-input-box" id="choice1" type="text" name="" value="" placeholder="Choice 1"> <br>
        <input class="text-input-box" id="choice2" type="text" name="" value="" placeholder="Choice 2"> <br>
        <input class="text-input-box invisible threeChoices" id="choice3" type="text" name="" value="" placeholder="Choice 3"> <br>
        <input class="text-input-box invisible fourChoices" id="choice4" type="text" name="" value="" placeholder="Choice 4">
      </div>
    </div>

  </div>

  <h5>The bigger number wins!</h5>
  <!-- Submit Button -->
  <a href="" id="submit" class="btn btn-info btn-lg" role="button">Go</a>
</div>
</body>

【问题讨论】:

  • 无法在另一个函数中获取局部变量。您可以返回值。
  • 那行不通。所有randomNumber 变量都在diceRoll 范围内,因此您无法在diceRoll 之外访问它们...但是有一种方法可以解决它。我会在下面告诉你。
  • 顺便说一句。你在links.forEach((el) =&gt; { ... })});忘记了一些右括号
  • @Sascha 我认为最后的结束 } 位于底部......还是我错过了另一个?对不起,我真的找不到它.. 好吧,nvm 我在底部又加了一个},谢谢
  • 不,这是来自document.getElementById("submit").addEventListener("click", function(e) { 中的函数(r) 使用 IDE 时,您会看到上述行中缺少 })

标签: javascript jquery google-chrome-devtools


【解决方案1】:

您不能引用这些值,您可以返回这些值并使用它们。简单的方法是使用数组。清理后的代码如下所示

function rollResult () {
  return Math.floor(Math.random() * 6 + 1);
}

function diceRoll() {

  var images = document.querySelectorAll("img");

  const dice = [];
  for (var i = 0; i<4; i++) {
    var number = rollResult();
    dice[i] = number;
    images[i+1].src = "dice" + number + ".png";
  }

  return dice;

}

var diceResult = diceRoll();
console.log(1, diceResult[0]);
console.log(2, diceResult[1]);
console.log(3, diceResult[2]);
console.log(4, diceResult[3]);

【讨论】:

    【解决方案2】:

    你可能不知道,但你问的是一个非常非常重要的 Javascript 概念,称为“作用域”。

    变量具有“范围”。将作用域视为一组可以访问变量的上下文。

    一个变量对它的“当前范围”和它下面的所有范围都是可见的。始终存在“全局”范围,也就是最外层的运行时环境。如果您查看diceRoll 函数定义之后的第一行可执行代码,您将看到一个全局范围变量的示例:links。变量links 可以从程序中的任何位置访问,只要你不使用某种模块捆绑器来修改幕后的范围(看起来你正在做一些非常基本的编程在这里,所以让我们暂时忘记它)。

    除了全局作用域,我们还有其他作用域。一个对你来说非常重要的理解是:函数范围。

    函数创建自己的范围。这意味着函数之外的任何内容都无法访问其中的内容。它是它自己的小自定义范围。您在其中定义的任何变量都无法在该函数之外访问。如果您考虑一下原因,就会发现:函数是临时代码。他们跑,然后他们就完成了。每次调用函数时,都会创建一个新作用域,处理函数逻辑,然后销毁所有变量引用,只要它们没有传递回调用上下文。这是设计使然。

    那么,您在这里所做的是创建变量,例如 randomNumber1,这些变量在函数 diceRoll 的范围之外根本不存在

    现在,更高级的编程技术会争辩说,您应该永远不要创建全局变量,我保证,您最终会学会遵守这一点。但是现在,您可以开始了解范围,解决问题的最简单方法是定义您的变量,它们diceRoll 函数之外,并内部将你的价值观分配给他们。基本上,这将解决您的问题:

    // Here, you **define** your variables. This "creates" them, but does not assign them values.
    var randomNumber1;
    var randomNumber2;
    var randomNumber3;
    var randomNumber4;
    var image1;
    var image2;
    var image3;
    var image4;
    
    // When code execution reaches this point, you could do something like this:
    console.log(randomNumber1);
    // ^ the above line would log `undefined` to the console, because the variable exists but has no value assigned to it. Great! We're all set, now all your global scope stuff further down can access these variables!
    
    function diceRoll() {
      // Now in here, you simply remove the *var* keyword, since you don't want to *create new variables*, you want to *assign values to the existing ones*. If you use the *var* keyword here, it will create a *new* variable with the same name, but only within the function scope. You will still have the same problem.
      randomNumber1 = Math.floor(Math.random() * 6 + 1);
      image1 = "dice" + randomNumber1 + ".png";
      document.querySelectorAll("img")[1].setAttribute("src", Image1);
    
      randomNumber2 = Math.floor(Math.random() * 6 + 1);
      image2 = "dice" + randomNumber2 + ".png";
      document.querySelectorAll("img")[2].setAttribute("src", Image2);
    
      randomNumber3 = Math.floor(Math.random() * 6 + 1);
      image3 = "dice" + randomNumber3 + ".png";
      document.querySelectorAll("img")[3].setAttribute("src", Image3);
    
      randomNumber3 = Math.floor(Math.random() * 6 + 1);
      image4 = "dice" + randomNumber3 + ".png";
      document.querySelectorAll("img")[4].setAttribute("src", Image4);
    }
    

    请注意,作为一个小的语义选择,我将您的 Image[x] 变量名称声明为驼峰式(首字母小写),这是行业标准约定。

    最后但同样重要的是,让我们回过头来重新阅读这里的重要内容,以帮助您找出问题:错误本身:

    index.js:91 Uncaught ReferenceError: randomNumber1 is not defined
      at HTMLAnchorElement.<anonymous> (index.js:91)
    

    让我们把它翻译成英文:

    Uncaught ReferenceError

    “未捕获”表示引发了错误(意味着您遇到了执行错误,因为您尝试执行由于某种原因无法执行的操作)。什么没被抓到?错误(始终是错误),特别是 ReferenceError 类型的错误。 正如我们乐于助人的朋友 MDN 告诉我们的那样: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError The ReferenceError object represents an error when a non-existent variable is referenced.

    基本上,您尝试访问尚未在当前范围(在您的情况下为全局范围)中定义的变量。

    最后:randomNumber1 is not defined 在哪里:

    at HTMLAnchorElement.&lt;anonymous&gt; (index.js:91) 范围,以便您可以正确引用该范围内的变量并解决您的问题。

    at HTMLAnchorElement.&lt;anonymous&gt; 指的是调用堆栈中的当前步骤及其上下文 - 但这更复杂,您现在可以忽略它。

    所以,总结一下:

    我们已将您要访问的变量声明移到您的函数范围之外,并保留了值的分配到这些变量,以便它仍然发生在您的函数中内部。理解这一点非常重要,我强烈建议您阅读一些有关 Javascript 和函数范围和闭包的内容。如果您想成为入门级 JS 开发人员,绝对需要了解这个概念

    很高兴回答您可能遇到的任何问题。祝你好运!

    编辑: @Mosia Thabo 的回答也是一个很好的例子,我认为“更正确的解决方案”。我没有故意提供那个解决方案,那是为了让这个问题与你的问题真正有关,即使你不知道。请注意,我提到“全局范围的变量是您要始终避免的事情”,您无疑会遇到“全局变量是邪恶的”这句话。他们是。

    我的例子是简化范围的概念,我认为这是在这里学习的重要一课。 Mosia 的回答是 我将如何处理它 - 该函数实际上基本上变成了您所说的生成器,为您提供结果集作为返回值。但是返回值会增加混乱,所以我把这部分省略了。

    范围。学习。关于。范围。

    【讨论】:

    • 谢谢!!这非常有用,现在将尝试您的方法
    • @argonx 不客气 - 我刚刚更新了答案以包含错误消息的描述,如果有帮助,这也有助于理解如何阅读。
    【解决方案3】:

    您需要整理语法错误。这个答案只提供了另一种方式来访问那些重要的randomNumber,您以后需要使用它们的值。

    正如我们已经在评论部分强调的那样,您不能在 Javascript 中直接访问该函数之外的函数作用域变量。您可以采取多种方法来实现这一目标......这是其中之一:

    diceRoll() 返回一个滚动的 resultObj,如下所示:

    function diceRoll() {
      var randomNumber1 = Math.floor(Math.random() * 6 + 1);
      var Image1 = "dice" + randomNumber1 + ".png";
      document.querySelectorAll("img")[1].setAttribute("src", Image1);
    
      var randomNumber2 = Math.floor(Math.random() * 6 + 1);
      var Image2 = "dice" + randomNumber2 + ".png";
      document.querySelectorAll("img")[2].setAttribute("src", Image2);
    
      var randomNumber3 = Math.floor(Math.random() * 6 + 1);
      var Image3 = "dice" + randomNumber3 + ".png";
      document.querySelectorAll("img")[3].setAttribute("src", Image3);
    
      var randomNumber4 = Math.floor(Math.random() * 6 + 1);
      var Image4 = "dice" + randomNumber4 + ".png";
      document.querySelectorAll("img")[4].setAttribute("src", Image4);
    
      return {
        One: {
          randomNumber: randomNumber1,
          image: Image1
        },
        Two: {
          randomNumber: randomNumber2,
          image: Image2
        },
        Three: {
          randomNumber: randomNumber3,
          image: Image3
        },
        Four: {
          randomNumber: randomNumber4,
          image: Image4
        }
      }
    }
    

    你会注意到我返回了一个带有 4 个键的对象,每个键代表一个骰子。每个骰子都有属性randomNumberimage。这样您就可以调用diceRoll 并稍后通过执行以下操作访问结果:

    var result = diceRoll();
    

    掷骰子,现在我们可以通过使用result 访问骰子的属性来获得结果...你可以这样做:

    
    // Determining Winner
    if (noOfChoices === "2") {if (result.One.randomNumber > result.Two.randomNumber) {$("#title").html(choice1 + " wins! ?");}
    else if (result.Two.randomNumber > result.One.randomNumber ) {$("#title").html(choice2 + " wins! ?");}
    else if (result.Two.randomNumber= result.One.randomNumber){$("#title").html("Oops, try again!");}
    }
    

    这适用于骰子 3 和 4。


    这是另一个更简单的版本:

    function diceRoll() {  
      let DiceKeys = ["One","Two","Three","Four"];
      let resultObject = {};
      
      DiceKeys.forEach((keyName, index)=>{
        let diceRandomNum = Math.floor(Math.random() * 6 + 1);
        let diceImageSrc = "dice" + diceRandomNum + ".png";
        document.querySelectorAll("img")[++index].setAttribute("src", diceImageSrc);
        
        resultObject[keyName] = {
          randomNumber: diceRandomNum,
          imageSrc : diceImageSrc
        };
      });
      
      return resultObject;
    }
    

    【讨论】:

    • 谢谢!现在就试试这个
    • 它在第 31 行显示意外标识符,即 Three: {,它指的是 {,知道为什么吗?
    • 对不起,我忘记把,放在返回对象上
    • 必须设置randomNumber的属性吗?现在它说index.js:32 Uncaught ReferenceError: randomNumber4 is not defined at diceRoll (index.js:32) at HTMLAnchorElement.&lt;anonymous&gt; (index.js:98)
    • 天哪,这也是我的错,我在电脑上改了,但问题上没有,现在试试
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-30
    • 1970-01-01
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 2021-11-20
    相关资源
    最近更新 更多