Method visibility is not supported by Javascript. There is no way to define a method on a class to be public or private. However we can make use of the Function bind syntax to emulate this behavior.

ES5 private functions

In ES5 we can take advantage of scope to wrap a block of context and only expose a public set of functions, tucking away private information in the scope that the public methods can access. In the example below, we’ll have a “counter” which will have a private method to log the updated count, and a set of public mutator methods.

var MyClass = (function MyClass () {
  // private
  var count = 0;

  function somePrivateMethod () {
    console.log('count updated', count);
  }

  // public
  return {
    add: function () {
      count++;
      somePrivateMethod()
    },
    subtract: function () {
      count--;
      somePrivateMethod();
    },
    getCount() {
      return count;
    }
  };
})();

ES7 private functions

ES2015 classes actually throw a bit of a wrench in this approach. We lose the concept of scope in a class. We don’t have a block that we can wrap private information and choose which information to make public. We only have a class structure to deal with.

class Counter() {
  constructor() {
    this.count = 0;
  },
  add() {
    this.count++;
    this.somePrivateMethod();
  }
  subtract() {
    this.count--;
    this.somePrivateMethod();
  }
  getCount() {
    return this.count
  }
  somePrivateMethod() {
    // not actually private
    console.log('count updated', count);
  }
}

Any method on the class is accessible from the outside - our private method is unfortunately forced into the public domain with the rest of the class.

Dumb private functions

We could take out the method from the class, place it outside, and call it by passing the count. The downside is that we turn this into a “dumb” function that requires passing in the context, rather than the private function being aware of the context. For example:

function somePrivateMethod(count) {
  console.log('count updated', count);
}
class Counter {
  //...
  add() {
    this.count++;
    somePrivateMethod(this.count);
  }
  //...
}

Function-Bind

With function-bind, ::, we can bind the context of the class instance to a function. Rather than passing in the pieces the function has to be made aware of, we can provide it with the entire this context, as if it another method on the class itself.

class Counter {
  //...
  add() {
    this.count++;
    this::somePrivateMethod();
  }
}

function somePrivateMethod() {
  console.log('count updated', this.count);
}

The magic here is this::somePrivateMethod(), which actually compiles down to somePrivateMethod.call(this). If you are unfamiliar with Function.prototype.call, it calls the function and uses the first argument as the function’s this.

When we do this::somePrivateMethod, that takes the left hand argument and uses it for the parameter to call, so we end up with somePrivateMethod.call(this).

Function-bind compiled

Using the Babel REPL, we can see this is true

function _classCallCheck(instance, constructor) { ... }
var Counter = (function () {
  function Counter() {
    _classCallCheck(this, Counter);
    this.count = 0;
  }

  Counter.prototype.add = function add() {
    this.count++;
    somePrivateMethod.call(this);
  };

  return Counter;
})();

function privateMethod() {
  console.log('count updated', this.count);
}

Do note that ES7 capabilities are considered experimental at this time. Babel does not support using these in production yet.