The biggest JavaScript OOP gotcha
Tags: javascript, beginners
Published: 2019-06-22 10:06:23

Object Oriented programming is very straightforward for most OOP languages but JavaScript is a bit different.

Given a game creator function, we want to extend the `game` object so it has some additional methods to increment the score `game.scorePoint()`.

> You can use [es6console](https://es6console.com/) to run our experiments.

Let's see the code:

```js
function GameCreator(score) {
    this.score = score;
}

GameCreator.prototype.scorePoint = function() {
	function incrementScore() {
    	this.score++;
    }
    incrementScore();
};

GameCreator.prototype.endGame = function() {
	console.log(`Game has finished ${this.score}`)
};

let game = new GameCreator(0);

game.scorePoint();
```

After executing this code you will notice that `game.score` is still `0`. But Why? What happened? Is our code wrong?

Yes it's wrong (but it looks fine, right?). First let's understand why it's wrong. Turns out `this` from `this.score++` represents the `window` object not the `game` instance. HA! Gotcha! That means our `score` is somewhere lost in the `window`.

So, the idea with this example is to understand that a **nested function** will not look up for the instance, in our case the `game` instance. Imagine for a moment that `scorePoint` not only has `incrementScore` but also `printScore`, but hey why not also another function `endGameWhenMaXScore`. See? The function could be splitted into small ones which is something great since it helps to organize the code, each function is reponsible for one little thing.

Now to fix the issue... we can use **Arrow Functions**:

```js
function GameCreator(score) {
    this.score = score;
}

GameCreator.prototype.scorePoint = function() {
	const incrementScore = ()=> {this.score++};
    incrementScore();
};

GameCreator.prototype.endGame = function() {
	console.log(`Game has finished ${this.score}`)
};

let game = new GameCreator(0);

game.scorePoint();
```

By using the `Arrow Function` we are indicating that we want to use the `game` instance instead of `window`.

Now `game.score;` will return `1`.


Using the constructor method:


```js
function GameCreator(score) {
    constructor (score) {
        this.score = score;
    }
    
    increment() {
    	this.score++;
    }
    
    endGame(){
    	console.log(`Game has finished ${this.score}`)
    }
}

let game = new GameCreator(0);

game.increment();
game.endGame();
```

Using ES6 classes [Classes - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes):

```js
class Game {
    constructor (score) {
        this.score = score;
    }
    
    increment() {
    	this.score++;
    }
    
    endGame(){
    	console.log(`Game has finished ${this.score}`)
    }

}

let game = new Game(0);

game.increment();
game.endGame();
```

See the code [running here](https://codesandbox.io/s/ecstatic-poitras-uv7uz)

Isn't it pretty? I like it, you like it, everybody does.

So, we have learn that `this` can be very tricky, still manageable. You just need to understand `this` on each context.

Try experimenting with the `this` keyword on different contexts and analyze the results. It will help you understanding how it works. At the end you will avoid a lot of mistakes and you will become a better JS developer!