этот код при первом запуске работает, но во второй раз показывает «Неперехваченный TypeError: не удается прочитать свойство ‘answer’ неопределенного»?

#javascript #html #jquery

#javascript #HTML #jquery

Вопрос:

 $(function() {
  $("#startBtn").hide();
  $(".questionPage").hide();
  $("#navUl a").click(
    function() {
      if ($(this).text() === "Math") {
        redayTest(testHtml);
      }
    });
  let testHtml = [{
      index: 0,
      question: "1 1=?",
      option: [0, 1, 2, 3],
      answer: "2"
    },
    {
      index: 1,
      question: "2 3=?",
      option: [3, 4, 5, 6],
      answer: "5"
    },
    {
      index: 2,
      question: "3 4=?",
      option: [7, 8, 9, 10],
      answer: "7"
    }
  ]

  let change = function(testItem, index) {
    let optionNumber = [0, 1, 2, 3, ];
    let randomNumber = optionNumber.sort(() => .5 - Math.random());

    $(".question").text(testItem[index].question);
    $("#option1").text(testItem[index].option[randomNumber[0]]);
    $("#option2").text(testItem[index].option[randomNumber[1]]);
    $("#option3").text(testItem[index].option[randomNumber[2]]);
    $("#option4").text(testItem[index].option[randomNumber[3]]);
  }

  let changeNumber = [0, 1, 2]
  let randomQuestionCount = 0;
  changeNumber = changeNumber.sort(() => .5 - Math.random());

  let redayTest = function(testItem) {

    $("#startBtn").show()
    $("#startBtn").click(function() {
      $(".questionPage").show();
      change(testItem, changeNumber[0]);
      console.log($("#option4,  #option3,  #option2,  #option1").text());
      console.log("answer = "   testItem[(changeNumber[randomQuestionCount])].answer);
      $(".questionPage button").click(function() {
        QuestionsCheck($(this), testItem);
      })
    })
  }

  let QuestionsCheck = function(option, testItem) {
    if (option.text() === testItem[(changeNumber[randomQuestionCount])].answer) {
      randomQuestionCount  ;

      if (randomQuestionCount === changeNumber.length) {
        console.log("done")
        $(".questionPage").hide();
        $("#startBtn").hide();
        $(".question").text("done");
      } else {
        change(testItem, changeNumber[randomQuestionCount]);
        console.log($("#option4,  #option3,  #option2,  #option1").text());
        console.log("answer = "   testItem[(changeNumber[randomQuestionCount])].answer);
      }
    } else {
      option.text("done")
    }
  }









})  
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<ul id="navUl">
  <li><a>Math</a></li>
</ul>

<button id="startBtn">check</button>
<p class="question"> </p>
<div class="questionPage">
  <button id="option1">A</button>
  <button id="option2">B</button>
  <button id="option3">C</button>
  <button id="option4">D</button>
</div>  

этот код при первом запуске работает

но во второй раз показывает «Неперехваченную ошибку типа: не удается прочитать свойство ‘answer’ неопределенного»

я не понимаю. потому что первое — это работа.

другая проблема я несколько раз нажимаю «Математика», прежде чем нажать «Проверить».

при нажатии проверьте после.

консоль.журнал несколько раз показывает ответ и значение параметра.

может ли вышеуказанная проблема с одним и тем же исходным кодом ошибки?

Спасибо.

Ответ №1:

Вам необходимо убедиться, что ваш код «startup» находится внутри события запуска, а не при запуске страницы.

В частности, ошибка указывает на этот код:

  testItem[(changeNumber[randomQuestionCount])].answer
  

говоря это testItem[(changeNumber[randomQuestionCount])] undefined , так что, вероятно, это randomQuestionCount не было сброшено.

Добавление

 randomQuestionCount = 0;
  

внутри startBtn.click сбросит позицию вопроса и удалит вашу ошибку.

Возможно, вы захотите рассмотреть init() функцию и поместить туда такую инициализацию (но это то же самое, что и внутри события click, просто понятнее, что он делает). Вы могли бы, например, также перемещаться changeNumber = changeNumber.sort(() => .5 - Math.random()); внутри init(), чтобы он менялся каждый раз.

 $(function() {
  $("#startBtn").hide();
  $(".questionPage").hide();
  $("#navUl a").click(
    function() {
      if ($(this).text() === "Math") {
        redayTest(testHtml);
      }
    });
  let testHtml = [{
      index: 0,
      question: "1 1=?",
      option: [0, 1, 2, 3],
      answer: "2"
    },
    {
      index: 1,
      question: "2 3=?",
      option: [3, 4, 5, 6],
      answer: "5"
    },
    {
      index: 2,
      question: "3 4=?",
      option: [7, 8, 9, 10],
      answer: "7"
    }
  ]

  let change = function(testItem, index) {
    let optionNumber = [0, 1, 2, 3, ];
    let randomNumber = optionNumber.sort(() => .5 - Math.random());

    $(".question").text(testItem[index].question);
    $("#option1").text(testItem[index].option[randomNumber[0]]);
    $("#option2").text(testItem[index].option[randomNumber[1]]);
    $("#option3").text(testItem[index].option[randomNumber[2]]);
    $("#option4").text(testItem[index].option[randomNumber[3]]);
  }

  let changeNumber = [0, 1, 2]
  let randomQuestionCount = 0;
  changeNumber = changeNumber.sort(() => .5 - Math.random());

  let redayTest = function(testItem) {

    $("#startBtn").show()
    $("#startBtn").off("click").click(function() {

      // init a new round here
      randomQuestionCount = 0;


      $(".questionPage").show();
      change(testItem, changeNumber[0]);
      console.log($("#option4,  #option3,  #option2,  #option1").text());
      console.log("answer = "   testItem[(changeNumber[randomQuestionCount])].answer);
      $(".questionPage button").click(function() {
        QuestionsCheck($(this), testItem);
      })
    })
  }

  let QuestionsCheck = function(option, testItem) {
    if (option.text() === testItem[(changeNumber[randomQuestionCount])].answer) {
      randomQuestionCount  ;

      if (randomQuestionCount === changeNumber.length) {
        console.log("done")
        $(".questionPage").hide();
        $("#startBtn").hide();
        $(".question").text("done");
      } else {
        change(testItem, changeNumber[randomQuestionCount]);
        console.log($("#option4,  #option3,  #option2,  #option1").text());
        console.log("answer = "   testItem[(changeNumber[randomQuestionCount])].answer);
      }
    } else {
      option.text("done")
    }
  }
})  
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<ul id="navUl">
  <li><a>Math</a></li>
</ul>

<button id="startBtn">check</button>
<p class="question"> </p>
<div class="questionPage">
  <button id="option1">A</button>
  <button id="option2">B</button>
  <button id="option3">C</button>
  <button id="option4">D</button>
</div>  


Кроме того, как правило, плохая идея вкладывать объявления обработчиков событий. Ваш код выполняет:

  • при navUL a нажатии добавьте новый обработчик событий в startBtn, чтобы при каждом запуске вы получали другой обработчик событий в startBtn, и он выполняется дважды / трижды и т.д. В приведенном выше фрагменте я смягчил это с помощью a .off("click") , но лучше объявлять обработчики событий на верхнем уровне (или, по крайней мере, не в другом обработчике событий).

У вас будет та же проблема $(".questionPage button").click , но я оставил это, поскольку проблема связана с randomQuestionCount сбросом.

Комментарии:

1. спасибо за ваше предложение. мне очень помогло изучить новый код «.off ()».