0

I am having trouble accessing the necessary object properties in a method. Here I have a simplified version of what I am trying to do. I have a Game class that is used to make a new game object. Once that object has been made I am trying to run the draw method. The draw method will use information from state.house.color, but I cannot seem to figure out how to access it since using "this" in draw will not refer to the game object. I have used .bind(this) in the past, but that doesn't seem to be helping here as I would need to bind an object not a function. Thanks for any insight!

class Game {
    state = {
        house: {
            color: "blue"    
        }
    }
    assets = {
        house: {
            draw(){
                //some logic here such as console.log(this.state.house.color)
            }
        }
    }
};

let testGame = new Game();

testGame.assets.house.draw();
Brenden
  • 60
  • 7
  • Well, it should be `new Game()` for a start. And why does the method need to be in a nested object? – Andy Jul 11 '22 at 19:48
  • Does this answer your question? [JavaScript: How to reference the top/root of a Class?](https://stackoverflow.com/questions/67755637/javascript-how-to-reference-the-top-root-of-a-class) – Jacob Stephenson Jul 11 '22 at 19:50
  • Does this answer your question? [How to access the correct \`this\` inside a callback](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback) – skara9 Jul 11 '22 at 19:55
  • Yes, both of those were great links and super helpful, I guess I just didn't know the search terms. Thanks! – Brenden Jul 11 '22 at 20:20

2 Answers2

2

Answer to your problem is arrow function, which won't override this.

class Game {
    state = {
        house: {
            color: "blue"    
        }
    }
    assets = {
        house: {
            draw: () => {
                console.log(this.state.house.color);
            }
        }
    }
}

let testGame = new Game()

testGame.assets.house.draw();

You can use bind too (worse in this case):

class Game {
    state = {
        house: {
            color: "blue"    
        }
    }
    assets = {
        house: {
            draw() {
                console.log(this.state.house.color);
            }
        }
    }
}

let testGame = new Game()

testGame.assets.house.draw.bind(testGame)();
PM75902693
  • 71
  • 3
  • Great! Works with the arrow function. Also seems to work if I use "draw: function(){console.log(this.state.house.color}.bind(this)". Thanks! – Brenden Jul 11 '22 at 20:20
0

While you could easily create an arrow function or a bound function that you put in the .assets.house.draw property, the real solution is not to nest properties in a class instance like that. Keep them top-level, don't try to namespace them.

If you really need to, create a separate class:

class House {
    constructor(color) {
        this.color = color;
    }
    draw() {
       console.log(this.color);
    }
}
class Game {
    house = new House("blue");
}

const testGame = new Game();
testGame.house.draw();

Pass anything that the house needs from the game into its constructor.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375