Title: Classes in Javascript - 2023 edition
Slug: classes-in-javascript-2023-edition
Date: 2023-04-11 19:15:00
Author: Kartones
Lang: en
Tags: Development, Javascript, Patterns & Practices
og_image:
Description: A summary of classes in JavaScript as of 2023, with examples including constructors, inheritance, getters, setters, static properties, private methods, and instantiation.


[MDN](https://developer.mozilla.org/en-US/docs/Web) is my go-to reference for anything web-related, even before doing a web search. But at times, it is structured too much as a reference guide, spreading over single pages every object property, every feature, every method... Which makes harder to get a general glimpse of a specific topic.

I wanted a quick refresh on what you can and cannot do, with Javascript, regarding classes, as of early 2023. I knew about class constructors, inheritance and recalled something about getters and setters, but for example I didn't knew about private scoping or the existence of `static` (I was going to go for the classic prototype modification). After reading everything about [JS classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes), I've written this small example containing an example of mostly everything on the topic of classes in JS:

```
// definition
class Movable {
  // public properties (can have default value)
  x;
  y;

  // constructor
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }

  // getter
  get position() {
    return [this.x, this.y];
  }

  // normal method
  move(x, y) {
    this.x = x;
    this.y = y;
  }
}

// inheritance
class Robot extends Movable {
  // private property + default value
  #movements = 0;
  // static property (can also be private) + default value
  static CAN_MOVE = true;

  // class constructor
  constructor(x = 0, y = 0) {
    // invoking parent constructor
    super(x, y);
    // not needed because of default value, but could do:
    // this.#movements = 0;
  }

  // static class constructor/initializer
  // static {}

  // getter
  get movements() {
    return this.#movements;
  }

  // setter
  set movements(value) {
    this.#movements = value;
  }

  // prepend `async` on methods when corresponds

  // normal method
  move(x, y) {
    // invoking parent method
    super.move(x, y);
    this.#movements++;
  }

  countAllMovements() {
    // invoking private method
    for (const count of this.#countMovements()) {
      console.log(`Movement #${count + 1}`);
    }
  }

  // static method
  static canMove() {
    // static properties must be used via class
    return Robot.CAN_MOVE;
  }

  // generator method + private method
  *#countMovements() {
    let counter = 0;
    while (counter < this.#movements) {
      yield counter++;
    }
  }
}

// instantiation
const myRobot = new Robot(5, 5);

// static methods must be invoked via class
console.log(Robot.canMove());

myRobot.move(7, 7);
myRobot.move(9, 9);
myRobot.move(10, 7);
console.log(myRobot.position, myRobot.movements);
myRobot.countAllMovements();
myRobot.movements = 0;
console.log(myRobot.movements);
```
