Mauric.io
Mauric.io

Reputation: 121

How to define private methods in a JS Class

I'm trying to define a private method for a class to test that such a method can't be called from outside the class. However, I'm coming across an error even when I'm using the syntax as indicated in the Specification. I also checked MDN.

Here's the code for my class:

class CoffeeMachine {
  #waterLimit = 200;

  #checkWater(value) {
    if (value < 0) throw new Error("Negative water");
    if (value > this.#waterLimit) throw new Error("Too much water");
  }
}

const coffeeMachine = new CoffeeMachine;

coffeeMachine.#checkWater();

Upon calling coffeeMachine.#checkWater();, I'm supposed to get an error indicating that such a method can't be called from outside the class, but instead, I'm getting Uncaught SyntaxError: Unexpected token '('.

What could be the reason for this?

Upvotes: 9

Views: 39632

Answers (5)

Nez Nez
Nez Nez

Reputation: 113

Might that be that you didn't actually instantiated the class instance in here:

 const coffeeMachine = new CoffeeMachine; 

It should be

const coffeeMachine = new CoffeeMachine();

(Notice the parenthesis () )

Upvotes: 0

undefined
undefined

Reputation: 1110

You are trying to access a private method from outside its class.

For environments with support for private fields, the following error is returned instead with the same code:

SyntaxError: Private field '#checkWater' must be declared in an enclosing class

This is expected behaviour. You may only access private fields within their enclosing class and only if they are declared. Any attempt to access private fields outside of their containing class (where they are not declared), including fields and classes that are not declared, will result in this syntax error.

For instance:

  • Chrome 94 (DevTools)
    Cannot access private fields from outside of enclosing class on Chrome 94
    Syntax error instead of ReferenceError

  • Node 14.7.4 (REPL server)
    Cannot access private fields from outside of enclosing class on Node v14

  • Your browser

    class CoffeeMachine {};
    const coffeeMachine = new CoffeeMachine;
    coffeeMachine.#notDeclared;

See more in the ECMAScript private class fields proposal (repo @tc39/proposal-private-fields, now part of @tc39/proposal-class-fields, stage 3).

Upvotes: 0

cicciosgamino
cicciosgamino

Reputation: 964

You example works in my Node.js 14.13.0 environment! Of course you need a public method to consume a private one. So here my working example:

   class CoffeeMachine {
     #waterLimit = 200

     #checkWater(value) {
       if (value < 0) throw new Error("Negative water")
       if (value > this.#waterLimit) throw new Error("Too much water")
       console.log(`@VALUE ${value}`)
     }

     checkWater(value) {
       this.#checkWater(value)
     }
   }

   const coffeeMachine = new CoffeeMachine()
   coffeeMachine.checkWater(20)

Upvotes: 1

Yureadingthis
Yureadingthis

Reputation: 71

In Javascript, you need to declare private variables private variables are declared by putting "#" in front of them (as seen in my example). Be sure to declare them outside of the constructor function

    class foo {
        #bar;// declare private variable called bar

        constructor() {
            this.#bar = "foobar";//define private variable called"bar"
        }
    }

Upvotes: 7

bafrimpong
bafrimpong

Reputation: 129

I think private methods (#myMethod()) and fields (#myField) are experimental features [source: developer.mozilar.org ] and at stage 3 for consideration but I managed to make it work by defining it to be as field and assigning it a function as follows;

#checkWater = (value) => {
  if (value < 0) throw new Error("Negative water");
  if (value > this.#waterLimit) throw new Error("Too much water");
}

OR

#checkWater = function(value) {
  if (value < 0) throw new Error("Negative water");
  if (value > this.#waterLimit) throw new Error("Too much water");
}

Now call it on the instance object as

coffeeMachine.#checkWater();

Let me hasten to add that, this code works in Google Chrome (1st image) but when tested in FireFox (2nd image), it did not run.

enter image description here

enter image description here

You should be okay with it hopefully!

Upvotes: 2

Related Questions