Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Enumerate Private JavaScript Class Fields

How do we enumerate through private class fields?

class Person {
  #isFoo = true;
  #isBar = false;

  constructor(first, last) {
    this.firstName = first;
    this.lastName = last;
  }

  enumerateSelf() {
    console.log(this);
    // (pub/priv fields shown)

    // enumerate through instance fields
    for (let key in this) {
      console.log(key)
      // (only public fields shown)
    }

    // How do we enumerate/loop through private fields too?
  }
}

new Person('J', 'Doe').enumerateSelf();
like image 440
AnthumChris Avatar asked Dec 22 '22 21:12

AnthumChris


2 Answers

It's not possible. They're private fields, and there is no enumeration method for them. Only the class declaration statically knows which ones were declared. They're not properties, there's not even a language value representing a private name, you cannot access them dynamically (like with bracket notation).

The best you'll get is

enumerateSelf() {
    console.log(this);
    for (let key in this) {
        console.log("public", key, this[key]);
    }
    console.log("private isFoo", this.#isFoo);
    console.log("private isBar", this.#isBar);
}

There was an open issue in the private-fields proposal about "Private field iteration", however one of the first comments by a TC39 member states "Private fields are not properties. You can't reflect on them by design.".

like image 173
Bergi Avatar answered Dec 28 '22 12:12

Bergi


Maybe not an elegant solution but perhaps you can modify your structure to do something like:

class Person {
  #properties = {
      isFoo: true,
      isBar: false
  };

  constructor(first, last) {
    this.firstName = first;
    this.lastName = last;
  }

  enumeratePrivateSelf() {
    // enumerate through private fields
    for (let key in this.#properties) {
      console.log(key)
      // (only public fields shown)
    }
  }
}
like image 31
Todd Kingham Avatar answered Dec 28 '22 10:12

Todd Kingham