Private Class Methods

Let's dig into another new feature coming to JavaScript in ES2021, shall we? This feature is called Private Class Methods.

Class Methods

If you've followed along with my various data structure blog posts, you'll be familiar with using creating classes and methods, but here's a little refresher using an example that's maybe more practical and easier to understand than a data structure:

class BankAccount {
  constructor(accountType, accountNumber) {
    this.accountType = accountType;
    this.accountNumber = accountNumber;
    this.balance = 0;
    console.log(`Your new ${accountType} account has been created!`);
  }
  deposit(depositAmount) {
    this.balance += depositAmount;
  }
  getAccountNumber() {
    console.log(`Your account number is ${this.accountNumber}.`);
  }
  getBalance() {
    console.log(`Your current account balance is \$${this.balance}.`);
  }
  withdrawal(withdrawalAmount) {
    this.balance -= withdrawalAmount;
  }
}

const checking = new BankAccount('Checking', 0123480);

The code above is a fairly simple program that allows a user to create a new bank account. It uses a class named BankAccount, which has a constructor method that accepts two parameters, accountType and accountNumber. You'll see 'Checking' and 0123480 passed as these respective arguments below the class definition when I actually create a new BankAccount and save it to the variable named checking. When the bank account gets constructed, it also sets a default property, named balance in addition to the passed accountType and accountNumber property values.

Otherwise out of the box this BankAccount class gives us some simple methods, like deposit(), which takes the amount you want to deposit and adds that to the balance, withdrawal(), which takes the amount you want to withdraw and subtracts it from the balance, or getBalance(), which simply prints out the account balance.

Using these methods is fairly straightforward after we've created the checking variable:

checking.deposit(100);
checking.withdrawal(55);
checking.getBalance();
// Expected result: "Your current account balance is $45."

Private Class Methods

Now say we have some private data or functionality in our bank account that we may need to use internally, but don't want to be exposed publicly. This is where Private Class Methods come into play. An example of some data you might want to protect but still be able to use internally might be an interest rate on the account.

I'm going to modify the above code by adding three things:

  1. a new property to our constructor called interestRate with the value of .005
  2. a new private method called getInterestRate()
  3. a new method called applyInterest()
class BankAccount {
  constructor(accountType, accountNumber) {
    this.accountType = accountType;
    this.accountNumber = accountNumber;
    this.balance = 0;
    this.interestRate = .005;
    console.log(`Your new ${accountType} account has been created!`);
  }
  applyInterest() {
    this.balance += (this.balance * this.#getInterestRate());
  }
  deposit(depositAmount) {
    this.balance += depositAmount;
  }
  getAccountNumber() {
    console.log(`Your account number is ${this.accountNumber}.`);
  }
  getBalance() {
    console.log(`Your current account balance is \$${this.balance}.`);
  }
  #getInterestRate() {
    return this.interestRate;
  }
  withdrawal(withdrawalAmount) {
    this.balance -= withdrawalAmount;
  }
}

const checking = new BankAccount('Checking', 0123480);

You'll notice above that the #getInterestRate() method definition has a # hash character in front of its name. This is what makes it a Private Class Method. As such we're unable to call it directly on the checking object:

checking.getInterestRate();
// Expected Result: TypeError: savings.getInterestRate is not a function

That said, you will also notice that we are able to call the method inside of the applyInterest() method. All this method does is apply the interest rate to the current balance and add that interest to the balance. It does so by calling #getInterestRate() like so: this.balance += (this.balance * this.#getInterestRate());.

So now let's run the following code:

checking.deposit(100);
checking.getBalance();
// Expected result: "Your current account balance is $100."
checking.applyInterest();
checking.getBalance();
// Expected result: "Your current account balance is $100.5."

So under the hood, applyInterest() is using the private #getInterestRate() method to get the interest rate, which we use to calculate and add interest. It's a trivial example, but I hope that it illustrates how and when you might go about using these new Private Class Methods.

From MDN: Class fields are public by default, but private class members can be created by using a hash # prefix. The privacy encapsulation of these class features is enforced by JavaScript itself.

See more examples and documentation here.