Skip to content

Instantly share code, notes, and snippets.

@rauschma
Last active April 27, 2020 13:04
Show Gist options
  • Save rauschma/2c55ef823e496320686dd4f475be7d7c to your computer and use it in GitHub Desktop.
Save rauschma/2c55ef823e496320686dd4f475be7d7c to your computer and use it in GitHub Desktop.

Cheat sheet: classes in JavaScript

Basic members of classes

class OtherClass {}

class MyClass1 extends OtherClass {

  publicInstanceField = 1;

  constructor() {
    super();
  }

  publicPrototypeMethod() {
    return 2;
  }
}

const inst1 = new MyClass1();
assert.equal(inst1.publicInstanceField, 1);
assert.equal(inst1.publicPrototypeMethod(), 2);

Modifier: static

class MyClass2 {

  static staticPublicField = 1;

  static staticPublicMethod() {
    return 2;
  }
}

assert.equal(MyClass2.staticPublicField, 1);
assert.equal(MyClass2.staticPublicMethod(), 2);

Modifier: # (private)

class MyClass3 {
  #privateField = 1;

  #privateMethod() {
    return 2;
  }

  static accessPrivateMembers() {
    // Private members can only be accessed from inside class definitions
    const inst3 = new MyClass3();
    assert.equal(inst3.#privateField, 1);
    assert.equal(inst3.#privateMethod(), 2);
  }
}
MyClass3.accessPrivateMembers();

Modifiers for accessors: get (getter) and set (setter)

There are two kinds of accessors: getters and setters.

class MyClass5 {
  #name = 'Rumpelstiltskin';
  
  /** Prototype getter */
  get name() {
    return this.#name;
  }

  /** Prototype setter */
  set name(value) {
    this.#name = value;
  }
}
const inst5 = new MyClass5();
assert.equal(inst5.name, 'Rumpelstiltskin'); // getter
inst5.name = 'Queen'; // setter
assert.equal(inst5.name, 'Queen'); // getter

Modifier for methods: * (generator)

class MyClass6 {
  * publicPrototypeGeneratorMethod() {
    yield 'hello';
    yield 'world';
  }
}

const inst6 = new MyClass6();
assert.deepEqual(
  [...inst6.publicPrototypeGeneratorMethod()],
  ['hello', 'world']);

Modifier for methods: async

class MyClass7 {
  async publicPrototypeAsyncMethod() {
    const result = await Promise.resolve('abc');
    return result;
  }
}

const inst7 = new MyClass7();
inst7.publicPrototypeAsyncMethod()
  .then(result => assert.equal(result, 'abc'));

Computed class member names

const publicInstanceFieldKey = Symbol('publicInstanceFieldKey');
const publicPrototypeMethodKey = Symbol('publicPrototypeMethodKey');

class MyClass8 {

  [publicInstanceFieldKey] = 1;

  [publicPrototypeMethodKey]() {
    return 2;
  }
}

const inst8 = new MyClass8();
assert.equal(inst8[publicInstanceFieldKey], 1);
assert.equal(inst8[publicPrototypeMethodKey](), 2);

Comments:

  • The main use case for this feature is symbols such as Symbol.iterator. But any expression can be used inside the square brackets.
  • We can compute the names of fields, methods, and accessors.
  • We cannot compute the names of private members (which are always fixed).

Combinations of modifiers

Fields:

level visibility
(instance)
(instance) #
static
static #

Methods:

level async accessor generator visibility
(prototype)
(prototype) get
(prototype) set
(prototype) async
(prototype) *
(prototype) async *
(prototype-associated) #
(prototype-associated) get #
(prototype-associated) set #
static
static get
static set
static async
static *
static async *
static #
static get #
static set #

Limitations of methods:

  • Private methods can’t be async or generators.
  • Getters and setters can’t be async or generators.

More information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment