0

I'm trying to understand OOP and this is my first real attempt. I'm confused why the word property variable in the init object is not available in the checkLetter function console.log even though I'm using the this keyword. In my pickWord function I'm able to use this.word with no issues. How can I make the word variable and this.word.length available to checkLetter?

var words = ["cancer", "aids", "stroke", "diabetes" ];

var keys = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'];

point = 0;

var init = {
  word: "",
  word_index: 0,
  point_status: 0,
  pickWord: function(){
    this.word = words[this.word_index];  
    this.displayDashes(this.word);
  },

  displayDashes: function(word){
    for(var i = 0; i< word.length; i++){
      var blankLetter = document.createElement("div");

      var hiddenletter = document.createTextNode(word[i]);
      blankLetter.appendChild(hiddenletter);

      blankLetter.classList.add('dashes');

      var wordHolder = document.getElementById('wordHolder');

      wordHolder.appendChild(blankLetter);


    }

  },

  addKeys: function(){
    for (var i = 0; i < keys.length; i++){
      var key = document.createElement("div");
      key.classList.add('keys');

      key.onclick = this.checkLetter;

      var letter = document.createTextNode(keys[i]);
      key.appendChild(letter);

      var keyboard = document.getElementById('keyboard');

      keyboard.appendChild(key);


    }
  },

  checkLetter: function(){

   var letterElems = document.getElementsByClassName('dashes');

   this.style.backgroundColor = 'blue';

   for(var i = 0; i < letterElems.length; i++){
     if(this.innerHTML == letterElems[i].innerHTML){
       letterElems[i].style.backgroundColor = 'white';
       pointStatus = point++;

     }
   }
  // checkPoints(pointStatus);
   // console.log(point); 
   console.log("the word: " + this.word); 

   if(point == this.word.length){
      alert('you won ' + point + " points so far!");
      this.nextWord();

    }  
  },


  nextWord: function(){
      alert('im inside nexword');
      this.word_index++;
      this.pickWord();
  }
}

init.pickWord();
init.addKeys();
// init.displayDashes();
oxxi
  • 382
  • 2
  • 10
  • 25
  • You seem to know that `this` in `checkLetter` *called as a click handler* refers to the clicked element, as you're using things like `this.style` or `this.innerHTML`. Why do you expect it to point to the `init` object at the same time? – Bergi Jul 13 '17 at 03:24
  • In your case the fix is easy, just refer to `init.word` instead. – Bergi Jul 13 '17 at 03:26
  • I expected to point to the object because it gets created inside the object. So the reason it doesn't work originally is because I create the onclick in the `addKeys` function and then try to use `word` by itself in the `checkLetter` function it looses the reference to the `this` keyword from the object? – oxxi Jul 13 '17 at 18:08
  • [Not quite](https://stackoverflow.com/q/3127429/1048572). It doesn't "loose" the reference, it never had one in the first place. The value of `this` is only determined by how the function is called. – Bergi Jul 13 '17 at 20:52

1 Answers1

1

The key.onclick event handler is called in the context of the element. So 'this' is the element. There are numerous ways to work around this issue. One such way is to bind the value of 'this' to the init object:

key.onclick = this.checkLetter.bind(this);

Edit: if you need access to the event handler's element, you can include the event as a function parameter, and access the element using the 'currentTarget' property. E.g. evt.currentTarget.

checkLetter: function(evt){
    var elem = evt.currentTarget;
  • I did the `this.checkLetter.bind(this);` in the addKeys function and now it doesn't run when I click the elements. Also how would I access the `word` variable in the `checkLetter` function? Like this: `if(point == elem.word.length)` ? – oxxi Jul 14 '17 at 05:32
  • It took me a while for things to make sense but all I had to do was `if(elem.innerHTML == letterElems[i].innerHTML)` and then it all started to work and I could use `if(point == this.word.length)`. This problem has helped me learn so much about `this` – oxxi Jul 14 '17 at 05:50
  • That's great! My JavaScript programming improved dramatically when I learned how `this` works. – programming for fun Jul 14 '17 at 22:58