Как отладить проблемы с объектами JavaScript?

1

Я прочитал этот учебник по JavaScript и столкнулся с проблемой, и я надеюсь, что кто-то сможет мне помочь. После выбора последнего вопроса в викторине моя showScore() отображает результаты как "undefined". После некоторой дополнительной отладки я обнаружил, что это проблема с моим объектом викторины. В моей PopulateQuestion() функции, я могу распечатать объект викторины перед выполнением showScore() функции. Однако, когда я пытаюсь распечатать объект викторины из функции showScore(), он возвращает undefined.

Я хотел бы работать над моей способностью отлаживать проблемы, которые возникают именно так. На основе отладки, которую я сделал до сих пор, моя образованная догадка заключается в том, что это проблема с областью, но я застрял. У кого-нибудь есть предложения по отладке этого дальше?

Вот мой код

Index.html

 <!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>JS Quiz</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="//main.css">
  </head>
  <body>
    <div class="quiz-container">
      <div id="quiz">
        <h1>Star Wars Quiz</h1>
        <hr style="margin-top: 20px;" />
        <p id="question">Who is Darth Vader?</p>
        <div class="buttons">
          <button id="b0"><span id="c0"></span></button>
          <button id="b1"><span id="c1"></span></button>
          <button id="b2"><span id="c2"></span></button>
          <button id="b3"><span id="c3"></span></button>
        </div>
        <hr style="margin-top: 50px" />
        <footer>
          <p id="progress">Question x of n</p>
        </footer>
      </div>
    </div>
    <script src="//quiz-controller.js"></script>
    <script src="//question.js"></script>
    <script src="//app.js"></script>
  </body>
</html>

//app.js

function populateQuestion() {
  if(quiz.isEnded()) {
    // display score
    console.log(quiz);
    showScore();
  } else {
    // display question
    var qElement = document.getElementById('question');
    qElement.innerHTML = quiz.getCurrentQuestion().text;

    // display choices
    var choices = quiz.getCurrentQuestion().choices;
    for(var i = 0; i < choices.length; i++) {
      var choice = document.getElementById('c' + i);
      choice.innerHTML = choices[i];
      guess("b" + i, choices[i]);
    }
    showProgress();
  }
}

function guess(id, guess) {
    var button = document.getElementById(id);
    button.onclick = function() {
      quiz.guess(guess);
      populateQuestion();
    };
}

function showProgress() {
    var currentQuestionNum = quiz.questionIndex + 1;
    var progress = document.getElementById("progress");
    progress.innerHTML = "Question " + currentQuestionNum + " of " + quiz.questions.length;
}

function showScore() {
  console.log(quiz);
  var resultsHTML = "<h1>Results</h1>";
  resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
  var quiz = document.getElementById("quiz");
  quiz.innerHTML = resultsHTML;
}

var questions = [
  new Question("Who is Darth Vader?",
  ["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
  "Anakin Skywalker"),
  new Question("What is the name of the third episode?",
  ["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
  "Revenge of the Sith"),
  new Question("Who is Anakin Skywalker son?",
  ["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
  "Luke Skywalker"),
  new Question("What is the name of the sixth episode?",
  ["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
  "Return of the Jedi")
];

var quiz = new Quiz(questions);
populateQuestion();

//question.js

function Question(text, choices, answer) {
  this.text = text;
  this.choices = choices;
  this.answer = answer;
}

Question.prototype.correctAnswer = function(choice) {
  return choice === this.answer;
};

Тест-controller.js

function Quiz(questions) {
  this.score = 0;
  this.questionIndex = 0;
  this.questions = questions;
}

Quiz.prototype.getScore = function() {
    return this.score;
};

Quiz.prototype.getCurrentQuestion = function() {
  return this.questions[this.questionIndex];
};

Quiz.prototype.isEnded = function() {
  return this.questionIndex === this.questions.length;
};

Quiz.prototype.guess = function(answer) {
  if(this.getCurrentQuestion().correctAnswer(answer)) {
    this.score++;
  }

  this.questionIndex++;
};
Теги:
debugging

2 ответа

2
Лучший ответ

Ваша проблема в том, что в функции showScore() вы определяете локальную переменную с quiz имени. Эта локальная переменная скрывает глобальную переменную с тем же именем (даже если она определена позже в коде).

Вы можете легко исправить это, переименовав свою локальную переменную в showScore (ниже показано как q вместо quiz):

function populateQuestion() {
  if(quiz.isEnded()) {
    // display score
    console.log(quiz);
    showScore();
  } else {
    // display question
    var qElement = document.getElementById('question');
    qElement.innerHTML = quiz.getCurrentQuestion().text;

    // display choices
    var choices = quiz.getCurrentQuestion().choices;
    for(var i = 0; i < choices.length; i++) {
      var choice = document.getElementById('c' + i);
      choice.innerHTML = choices[i];
      guess("b" + i, choices[i]);
    }
    showProgress();
  }
}

function guess(id, guess) {
    var button = document.getElementById(id);
    button.onclick = function() {
      quiz.guess(guess);
      populateQuestion();
    };
}

function showProgress() {
    var currentQuestionNum = quiz.questionIndex + 1;
    var progress = document.getElementById("progress");
    progress.innerHTML = "Question " + currentQuestionNum + " of " + quiz.questions.length;
}

function showScore() {
  console.log(quiz);
  var resultsHTML = "<h1>Results</h1>";
  resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
  var q = document.getElementById("quiz");
  q.innerHTML = resultsHTML;
}

var questions = [
  new Question("Who is Darth Vader?",
  ["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
  "Anakin Skywalker"),
  new Question("What is the name of the third episode?",
  ["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
  "Revenge of the Sith"),
  new Question("Who is Anakin Skywalker son?",
  ["Luke Skywalker", "Anakin Skywalker", "Your Mom", "Your Dad"],
  "Luke Skywalker"),
  new Question("What is the name of the sixth episode?",
  ["Return of the Jedi", "Revenge of the Sith", "A New Hope", "The Empire Strikes Back"],
  "Return of the Jedi")
];

function Question(text, choices, answer) {
  this.text = text;
  this.choices = choices;
  this.answer = answer;
}

Question.prototype.correctAnswer = function(choice) {
  return choice === this.answer;
};

function Quiz(questions) {
  this.score = 0;
  this.questionIndex = 0;
  this.questions = questions;
}

Quiz.prototype.getScore = function() {
    return this.score;
};

Quiz.prototype.getCurrentQuestion = function() {
  return this.questions[this.questionIndex];
};

Quiz.prototype.isEnded = function() {
  return this.questionIndex === this.questions.length;
};

Quiz.prototype.guess = function(answer) {
  if(this.getCurrentQuestion().correctAnswer(answer)) {
    this.score++;
  }

  this.questionIndex++;
};

var quiz = new Quiz(questions);
populateQuestion();
 <!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>JS Quiz</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="//main.css">
  </head>
  <body>
    <div class="quiz-container">
      <div id="quiz">
        <h1>Star Wars Quiz</h1>
        <hr style="margin-top: 20px;" />
        <p id="question">Who is Darth Vader?</p>
        <div class="buttons">
          <button id="b0"><span id="c0"></span></button>
          <button id="b1"><span id="c1"></span></button>
          <button id="b2"><span id="c2"></span></button>
          <button id="b3"><span id="c3"></span></button>
        </div>
        <hr style="margin-top: 50px" />
        <footer>
          <p id="progress">Question x of n</p>
        </footer>
      </div>
    </div>
    <script src="//quiz-controller.js"></script>
    <script src="//question.js"></script>
    <script src="//app.js"></script>
  </body>
</html>
  • 0
    Спасибо, Фриджон! Я вижу, где я сделал свою ошибку сейчас. Я исправил это, и это сработало.
0

Существует приватная переменная опрос в функции showScore, которая поднимается вверху функции следующим образом:

Your code:
function showScore() {
    console.log(quiz);
    var resultsHTML = "<h1>Results</h1>";
    resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
    var quiz = document.getElementById("quiz");

    What internally happens:
        function showScore() {
            var quiz = undefined; // hoisting is happening here. So quiz is not reffering to public quiz variable anymore.
            console.log(quiz);
            var resultsHTML = "<h1>Results</h1>";
            resultsHTML += "<h2 id='score'>Your Score: " + quiz.getScore() + "</h2>";
            var quiz = document.getElementById("quiz");

Ещё вопросы

Сообщество Overcoder
Наверх
Меню