How to Create Private Methods in JavaScript with Public Access Restrictions

How can I create a JavaScript private methods with a public method like: function Restaurant() {}

Restaurant.prototype.buy_food = function() { // something here }

Restaurant.prototype.use_restroom = function() { // something here }

This allows users of my class to call: var restaurant = new Restaurant(); restaurant.buy_food(); restaurant.use_restroom();

Now, I want to define a private method that can be called by the buy_food and use_restroom methods but cannot be accessed externally.

For instance, I want this to work:

Restaurant.prototype.use_restroom = function() { this.private_stuff(); }

But I want to prevent this from working: var r = new Restaurant(); r.private_stuff();

How do I define private_stuff as a private method in JavaScript so that it can only be used internally within the class but not accessed publicly?

If you’re looking to make private_stuff inaccessible externally, closures are a simple and effective way in JavaScript to create private methods. Here’s how you can do it inside the constructor function, which keeps private_stuff out of the prototype and invisible to any outside code._

function Restaurant() {
  // Private method
  var private_stuff = function() {
    console.log("Doing private stuff");
  };

  this.buy_food = function() {
    private_stuff();
    console.log("Buying food");
  };

  this.use_restroom = function() {
    private_stuff();
    console.log("Using restroom");
  };
}

var restaurant = new Restaurant();
restaurant.buy_food(); // Works
restaurant.use_restroom(); // Works
// restaurant.private_stuff(); // Error: private_stuff is not a function

This approach with closures is perfect for keeping private_stuff inaccessible, making it one of the cleaner ways to implement javascript private methods in constructor functions.

Now, if you’re using modern JavaScript (ES6 and beyond), the # syntax makes it possible to create truly private fields and methods in classes. Using # keeps private_stuff accessible only within the class context. Here’s an example:_

class Restaurant {
  // Private method
  #private_stuff() {
    console.log("Doing private stuff");
  }

  buy_food() {
    this.#private_stuff();
    console.log("Buying food");
  }

  use_restroom() {
    this.#private_stuff();
    console.log("Using restroom");
  }
}

let restaurant = new Restaurant();
restaurant.buy_food(); // Works
restaurant.use_restroom(); // Works
// restaurant.#private_stuff(); // Syntax Error: Private field '#private_stuff' must be declared in an enclosing class

In ES2022, this # syntax really is a clean solution if you’re working with classes and want clear-cut javascript private methods.

Another approach worth considering, especially if you’re working across different instances of an object, is using a WeakMap to handle private methods. This pattern ensures that private methods remain accessible only to internal functions while being entirely hidden from public access._

const privateStuff = new WeakMap();

function Restaurant() {
  // Set up private method in WeakMap
  privateStuff.set(this, function() {
    console.log("Doing private stuff");
  });

  this.buy_food = function() {
    privateStuff.get(this)();
    console.log("Buying food");
  };

  this.use_restroom = function() {
    privateStuff.get(this)();
    console.log("Using restroom");
  };
}

var restaurant = new Restaurant();
restaurant.buy_food(); // Works
restaurant.use_restroom(); // Works
// restaurant.private_stuff(); // Error: private_stuff is not defined

This WeakMap approach is a solid alternative for javascript private methods, especially when you need private access across multiple instances without modifying the class itself.