0
class Player {
  constructor() {
    this.health = 100;
  }
  playerDamaged(applyDamage) {
    applyDamage(this);
  }
}

class BrickWall {
  constructor() {
    this.collisionDmg = 5;
  }
  playerCollision(player) {
    player.health -= BrickWall.collisionDmg;
  }
}

class SpikyWall {
  constructor() {
    this.collisionDmg = 25;
  }
  playerCollision(player) {
    player.health -= SpikyWall.collisionDmg;
  }
}

const player = new Player();
const brickWall = new BrickWall();
const spikyWall = new SpikyWall();

player.playerDamaged(brickWall.playerCollision);
player.playerDamaged(spikyWall.playerCollision);

console.log(player.health);

In the Player class I want to be able to pass a callback to playerDamaged to apply damage to the Player's health.

My intended objective is that line when player.playerDamaged(brickWall.playerCollision); runs, the player's health will be reduced by 5, and when player.playerDamaged(brickWall.playerCollision); runs, the player's health will be reduce by another 25.

I want console.log(player.health); to return 70. It currently returns NaN.

Thanks for any assistance you can offer!

dblinkhorn
  • 41
  • 7

1 Answers1

1

With this

player.health -= BrickWall.collisionDmg;

you're referring to BrickWall.collisionDmg - which would only make sense if the property is on the class itself, like so:

class BrickWall {
  static collisionDmg = 5;
  playerCollision(player) {
    player.health -= BrickWall.collisionDmg;
  }
}

or

class BrickWall {
  playerCollision(player) {
    player.health -= BrickWall.collisionDmg;
  }
}

BrickWall.collisionDmg = 5;

The class is not the instance; the instance does not inherit from the class as a prototype. (The instance inherits from the <class>.prototype, but not from <class>) So, since no property exists at BrickWall.collisionDmg in your code, it returns undefined, resulting in NaN.

Add the static properties.

class Player {
  constructor() {
    this.health = 100;
  }
  playerDamaged(applyDamage) {
    applyDamage(this);
  }
}

class BrickWall {
  static collisionDmg = 5;
  playerCollision(player) {
    player.health -= BrickWall.collisionDmg;
  }
}

class SpikyWall {
  static collisionDmg = 25;
  playerCollision(player) {
    player.health -= SpikyWall.collisionDmg;
  }
}

const player = new Player();
const brickWall = new BrickWall();
const spikyWall = new SpikyWall();

player.playerDamaged(brickWall.playerCollision);
player.playerDamaged(spikyWall.playerCollision);

console.log(player.health);

That said, I don't think having classes for BrickWall and SpikyWall are doing that much for you here (other than making the logic uncomfortably weird to follow due to the callbacks). A class is useful when you want to tie together data associated with an instance with methods to operate on that data - but you don't have any instance data. JS isn't Java, so don't feel like you have to use a class just because the keyword exists. Consider a plain function instead, and then call that function, perhaps like:

const brickWall = player => player.health -= 25;

or

const COLLISION_DAMAGE = {
  brickWall: 5,
  spikeyWall: 25,
};
// ...
player.playerDamaged(COLLISION_DAMAGE.brickWall);
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320