skip to Main Content

I’m having trouble trying to figure out why I am not able to use ‘this.count’ in a prototype of my Game constructor without getting NaN or undefined. I am using it to track points every time the user answers one of four questions correctly.

I had assumed that once a property was declared inside a constructor, it is available for use in any of its prototypes? Thank you in advance.

var questions = [
  {question: "What programming language does the library 'jQuery' belongs to?",
  answer: "JAVASCRIPT"},
  {question: "What programming language does 'Sass' builds upon?",
  answer: "CSS"},
  {question: "How do you abbreviate Hyper Text Markup Language?",
  answer: "HTML"},
  {question: "What company does the framework 'Bootstrap' belong to?",
  answer: "TWITTER"}
];

var Game = function(array) {
  this.array = array;
  this.count = 0;   // this.count is set to 0 //
}

var guess = new Game(questions);

Game.prototype.play = function() {
  console.dir(this.array);
  console.dir(this.count);
  $('button').click(function() {
    for (var i = 0; i < this.array.length; i++) {
        var newGuess = prompt(this.array[i].question).toUpperCase();
        if (newGuess === this.array[i].answer) {
            ++this.count;    // Problem happens here //
            console.log(this.count);
        } else {
            alert('Incorrect.');
        }
    }
    alert('You answered ' + this.count + ' out of 4 correct.');
  });
}
guess.play();

2

Answers


  1. It’s because the this you are referring to is the this of the click handler function, which does not contain count:

    Solution 1 – this alias:

    Game.prototype.play = function() {
    var that = this; // the alias
    
      console.dir(this.array);
      console.dir(this.count);
      $('button').click(function() {
        for (var i = 0; i < this.array.length; i++) {
            var newGuess = prompt(this.array[i].question).toUpperCase();
            if (newGuess === this.array[i].answer) {
                ++this.count;    // Problem happens here //
                console.log(this.count);
            } else {
                alert('Incorrect.');
            }
        }
        alert('You answered ' + that.count + ' out of 4 correct.'); // using the alias
      });
    }
    

    Solution 2 – using bind to change this:

      $('button').click(function() {
        for (var i = 0; i < this.array.length; i++) {
            var newGuess = prompt(this.array[i].question).toUpperCase();
            if (newGuess === this.array[i].answer) {
                ++this.count;    // Problem happens here //
                console.log(this.count);
            } else {
                alert('Incorrect.');
            }
        }
        alert('You answered ' + this.count + ' out of 4 correct.');
      }.bind(this)); // the this of the outer closure is now the this of the click handler function
    
    Login or Signup to reply.
  2. Inside of the anonymous function the ‘this’ is referencing the anonymous function itself, not Game. Add:

        var self = this;
    

    before the .click(…) and replace the ‘this’ with ‘self’.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search