0

I have a module pattern with a variable setting the currentPlayer to 1. I use a function expression to toggle that variable

 const game = (() => {
    let currentPlayer = 1;

    const toggleCurrentPlayer = () => {
        if (currentPlayer == 1){
            currentPlayer = 2 ;
        }
        else {
            currentPlayer = 1;
        }
    };
    return {currentPlayer, toggleCurrentPlayer};
})();

If I run game.currentPlayer it logs 1, I then run game.toggleCurrentPlayer(), and it doesn't change currentPlayer as intended, it still returns 1.

However, changing the toggleCurrentPlayer() function using this, seems to be able to change the variable successfully

function toggleCurrentPlayer(){
    if (this.currentPlayer == 1){      
        this.currentPlayer=2;
    }
    else if (this.currentPlayer == 2){
        this.currentPlayer=1;
    }
};

I know function declarations and function expressions have different meanings for the keyword this, but why would the toggleCurrentPlayer() only work properly with the this keyword and not be able to set the variable on its own?

5
  • 1
    The difference has nothing to do with the way toggleCurrentPlayer is declared. It's about modifying a local variable vs. modifying an object property. Commented Aug 10, 2020 at 23:57
  • @Bergi So I can only modify the object property inside the module, but I cannot assign a new value to the variable inside the module? Commented Aug 10, 2020 at 23:59
  • 2
    Your first code does toggle the local variable just fine. The problem is that the game.currentPlayer property is not a live view on the variable, it just keeps the value that you created initially. Commented Aug 11, 2020 at 0:01
  • 1
    (And you've got it backwards: any code from outside the module can assign the object property using game.currentPlayer = 3;, but only the code inside the module scope can access and assign the local variable let currentPlayer) Commented Aug 11, 2020 at 0:03
  • I wonder how he can change the currentPlayer variable inside game Commented Aug 12, 2020 at 6:17

1 Answer 1

2

When the function does

return {currentPlayer, toggeleCurrentPlayer};

It copies the initial value of the currentPlayer variable into the object.

The returned object contains the value of the variable, not a reference to the variable itself. Reassigning the variable has no effect on the object.

What you can do instead is create an object inside the function, and modify that.

const game = (() => {
  let obj = {
    currentPlayer: 1,
    toggleCurrentPlayer: () => {
      if (obj.currentPlayer == 1) {
        obj.currentPlayer = 2;
      } else {
        obj.currentPlayer = 1;
      }
    }
  };
  return obj;
})();

console.log(game.currentPlayer);
game.toggleCurrentPlayer();
console.log(game.currentPlayer);

Another way to do it is with a getter function that retrieves the variable.

const game = (() => {
    let currentPlayer = 1;

    const toggleCurrentPlayer = () => {
        if (currentPlayer == 1){
            currentPlayer = 2 ;
        }
        else {
            currentPlayer = 1;
        }
    };
    const getCurrentPlayer = () => currentPlayer
    return {getCurrentPlayer, toggleCurrentPlayer};
})();

console.log(game.getCurrentPlayer());
game.toggleCurrentPlayer();
console.log(game.getCurrentPlayer());

Sign up to request clarification or add additional context in comments.

8 Comments

In that case you wouldn't even need the IIFE
Without the IIFE where would I get a scope for obj? I could change it to use game.currentPlayer in the toggle function.
Oops, I missed that you had not used this in a method but an arrow function closing over obj. But yeah, given that game is const anyway, using that seems fine as well.
It's accessing a variable saved in the closure.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.