Private in JavaScript ESNext (Part 3)

In the previous two posts we talked about how to create “private” fields for a class. Those involved kind of convoluted mechanisms like closure or WeakMaps.

JavaScript is constantly evolving and in the new ES2019 standard there is a clean way of creating “private” fields of a class

Let's see how ES2019 creates private
class Account {

    // True private fields
    #id = 0;
    #name = "";
    #balance = 0;

    constructor(id, name, balance) {
        this.#id = id;
        this.#name = name;
        this.#balance = balance;

    }

    withdraw(amount) {
        this.#balance -= amount;
    }

    deposit(amount) {
        this.#balance += amount;
    }

    print() {
        console.log(
            `ID: ${this.#id}`,
            `Name: ${this.#name}`,
            `Balance: ${this.#balance}`
        );
    }
}

let eich = new Account(1, "Brendan", 10000);
eich.print(); 

// This doesn't work
eich.#balance = 50000;
And here is the output
ID: 1 Name: Brendan Balance: 10000

eich.#balance = 50000;
^
SyntaxError: Private field '#balance' must be declared in an enclosing class

That’s it! No more closures, Symbols or WeakMaps to implement private in JavaScript latest version.
But JavaScript… why oh why, did you not use the reserved word private??? It would have been so simple to write something like

// Warning: This is NOT valid syntax

class Account {

    // What it COULD have been
    private id = 0;
    private name = "";
    private balance = 0;

    constructor(id, name, balance) {
        this.id = id;
        this.name = name;
        this.balance = balance;

    }

    withdraw(amount) {
        this.balance -= amount;
    }

    deposit(amount) {
        this.balance += amount;
    }

    print() {
        console.log(
            `ID: ${this.id}`,
            `Name: ${this.name}`,
            `Balance: ${this.balance}`
        );
    }
}

However, there is one thing STILL elusive, even in the latest version of JavaScript.. private functions. There is still no way to mark a function as private. So the following still doesn’t work

class Account {

    // True private fields
    #id = 0;
    #name = "";
    #balance = 0;

    constructor(id, name, balance) {
        this.#id = id;
        this.#name = name;
        this.#balance = balance;
    }

    // Cannot create private functions
    // # works on variables but not functions
    #sendSms() {
        console.log(`Sms Sent: Updated balance=${this.#balance}`);    
    }

    withdraw(amount) {
        this.#balance -= amount;
    }

    deposit(amount) {
        this.#balance += amount;
    }

    print() {
        console.log(
            `ID: ${this.#id}`,
            `Name: ${this.#name}`,
            `Balance: ${this.#balance}`
        );
    }
}

let eich = new Account(1, "Brendan", 10000);
eich.print();

So, the question remains… what is the most elegant way of creating private functions in ES6 or later such that we don’t land up adding the same function in EVERY instantiated object.

If you have ideas, drop me a comment

Private in JavaScript Series

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s