The `this` binding gotcha
this is bound by how the method is called, not by where it's written:
const e = new Entity(10, 20, 40, 56);
const func = e.moveX; // pull the method off the object
func(5); // this is NOT e here, it's undefined
When you call a method like e.moveX(5), this = e. If you grab the method away and call it bare, this is lost. In the real game this never happens because methods are always called as object.method().
The same rule applies to arrow functions: an arrow's this is the enclosing scope, not the object. That's why game methods use regular function syntax or arrow methods written on the class body, where this stays bound to the instance.
Why classes matter for games
Without classes you'd write every object by hand, repeating the shape (x, y, w, h, vx, vy) for each of dozens of entities, and every method body typed out again. Add 30 obstacles and you have 30 copies of the same fields.
Classes give you:
- One shape, many objects. Define
Entityonce;newas many as you want. - Behaviour on the object.
player.jump(),coin.draw(ctx): the logic lives where the data does. - Inheritance. Ground, coins, hazards, and the player all share
Entity, adding only what differs.
The game's entities/ folder follows this exactly: Entity.js is the base, and each subtype overrides update(dt) and draw(ctx). The main loop just calls entity.update(dt) and entity.draw(ctx) on every object, and each class decides what to do, because they all share the same shape.