Using prototypes creating a Hangman game I have a Hangman object constructor with a couple of methods connected to it.

I would like to know how I should encapsulate the logic.

Can I have logic outside the methods (as I'm doing, like hangman.letters.push(e.key);) on document.onkeydown or should I only call the methods here and they should strictly run the game?

Any logic improvements are welcome! 

Thank you very much!



var hangman;

function Hangman() {
  this.words = ["sweden", "brazil", "spain", "germany"];
  this.secretWord = "";
  this.letters = [];
  this.guessedLetter = "";
  this.errorsLeft = 5;
  this.messages = {
    win: "You won!",
    loose: "Game over!",
    guessed: "You already guessed this letter, please try again..",
    notValidLetter: "Please enter a valid letter from a-z",
  };
}

Hangman.prototype._getWord = function() {
  return this.words[Math.floor(Math.random() * this.words.length)];
};

Hangman.prototype._checkIfLetter = function(keyCode) {
  return /^[a-zA-Z]*$/.test(String.fromCharCode(keyCode));
};

Hangman.prototype._checkClickedLetters = function(key) {
  return !this.letters.includes(key);
};

Hangman.prototype._addCorrectLetter = function(key) {
  if (this.secretWord.includes(key)) {
    console.log(`${key} is part of the secret word`);
    for (let ix = 0; ix &lt; hangman.secretWord.length; ix++) {
      if (hangman.secretWord[ix] === key) {
        this.guessedLetter += key;
      }
    }
    if (this._checkWinner()) {
      console.log(this.messages.win);
    }
  } else {
    console.log(`${key} is NOT part of the secret word`);
    this._addWrongLetter();
    if (this._checkGameOver()) {
      console.log(this.messages.loose);
    }
  }
};

Hangman.prototype._addWrongLetter = function(letter) {
  return this.secretWord.includes(letter)
    ? this.errorsLeft
    : (this.errorsLeft -= 1);
};

Hangman.prototype._checkGameOver = function() {
  return this.errorsLeft === 0;
};

Hangman.prototype._checkWinner = function() {
  return (
    this.secretWord
      .split("")
      .sort()
      .join("") ===
    this.guessedLetter
      .split("")
      .sort()
      .join("")
  );
};

document.getElementById("start-game-button").onclick = function() {
  hangman = new Hangman();
  hangman.secretWord = hangman._getWord();
  console.log(hangman.secretWord);
};

document.onkeydown = function(e) {
  if (hangman != undefined) {
    // Check if char is a valid alpha char.
    if (hangman._checkIfLetter(e.keyCode)) {
      // Check if we already
      if (hangman._checkClickedLetters(e.key)) {
        hangman._addCorrectLetter(e.key);
        hangman.letters.push(e.key);
      } else {
        console.log(hangman.messages.guessed);
      }
    }
  } else {
    console.log(hangman.messages.notValidLetter);
  }
};
.game-logo {

}

#start-game-button {
  border: 0;
  box-shadow: 0;
  background: linear-gradient(to bottom, #9DA400, #BAC600);
  color: #fff;
  padding: 20px 40px;
  font-size: 30px;
  border-radius: 5px;
}

#hangman {
  text-align: center;
}
&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
  &lt;meta charset="UTF-8"&gt;
  &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
  &lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
  &lt;link rel="stylesheet" href="stylesheets/styles.css"&gt;
  &lt;title&gt;The Hangman&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
  &lt;div style="text-align:center; margin: 50px 0px;"&gt;
    &lt;img src="http://www.firstcomicsnews.com/wp-content/uploads/2016/09/Hangman-Logo-600x253.png" alt="" class="game-logo"&gt;
  &lt;/div&gt;
  &lt;div style="text-align:center; margin: 50px 0px;"&gt;
    &lt;button id="start-game-button"&gt;START GAME&lt;/button&gt;
  &lt;/div&gt;
  &lt;div style="text-align:center;"&gt;
    &lt;canvas id="hangman" height="800px" width="1200px"&gt;&lt;/canvas&gt;
  &lt;/div&gt;
  &lt;script type="text/javascript" src="canvas.js"&gt;&lt;/script&gt;
  &lt;script type="text/javascript" src="hangman.js"&gt;&lt;/script&gt;

&lt;/body&gt;

&lt;/html&gt;
Encapsulation


  I would like to know how I should encapsulate the logic.
  
  Can I have logic outside the methods (as I'm doing, like
  hangman.letters.push(e.key); in document.onkeydown or should I only
  call the methods here and they should strictly run the game?


Ideally no internals should be exposed.
Using the hangman object should go more like this:

document.onkeydown = function(e) {
  if (hangman.guessLetter(e.keyCode)) {
    if (hangman.won()) {
      // congrats!
      // -&gt; display complete word
      // -&gt; clean up UI
    } else {
      // good guess!
    }
  } else {
    if (hangman.lost()) {
      // ouch, you lost
      // -&gt; clean up UI
    } else {
      // ouch, you missed, try again
    }
  }
  // -&gt; display word status, for example _we_e_ when "w" and "e" were already found in "sweden"
};


No properties of hangman should be accessed, only methods called.

Usability

The game looks incomplete:
the UI shows a large image and a button,
but expects input from the keyboard and writes messages to console.
It's hard to use like this.

Performance

The implementation of _checkWinner is inefficient.
It splits the secret word and the guess to their letters and joins them to compare to each other.
This operation is unnecessary for the secret word,
because once it's generated at the beginning of the game,
it never changes.
So it would be better to generate the word with sorted letters up front.