Qubyte Codes

Private methods for JS classes

This is a short companion to an earlier article I wrote on using WeakMap for private data with JS classes. While private data belongs to instances, private methods can be shared between instances of a class (just like its regular methods). An implementation using ES2015 modules looks like:

function setContent(content) {
  const text = document.createTextNode(content);

  this.el.appendChild(text);
}

export default class Paragraph {
  constructor(content) {
    this.el = document.createElement('p');

    setContent.call(this, content);
  }

  replace(content) {
    this.el.innerHTML = '';

    setContent.call(this, content);
  }
}

This module exports a class which wraps a paragraph element (which is not a particularly useful thing to do, but hopefully illustrates what I'm about to say).

Each instance of Paragraph is constructed with some content. The one public method it has is replace, which allows the content to be replaced. Both the constructor and the replace methods set content, so rather than repeat the code that does that, the code is placed in the private method setContent. setContent operates on a Paragraph instance passed in as the context by using call. You could just as easily pass the instance in by using a parameter. I've chosen the former approach here to keep the difference between public and private methods to the minimum.

By virtue of the setContent method being declared outside of the class declaration, the class does not make it available. You control which things you export from the module, so if the class doesn't make replace available, and the module doesn't export it, then nothing outside the module has access. Thus setContent is a private method.

For clarity, replace being public means that I can do this:

var paragraph = new Paragraph('hello');

// replace is pubic, so we can use it.
paragraph.replace('goodbye');

And setContent being private means that I cannot do this:

var paragraph = new Paragraph('hello');

// setContent is not a part of the Paragraph
// definition. We cannot do this.
paragraph.setContent('goodbye');

So there you have it. There's not a lot to the pattern really. Earlier module types and patterns allow the same thing to be done. I recommend reading the section on module patterns in Addy Osmani's excellent book Learning JavaScript Design Patterns if you want to know more (and particularly the sub section on the module pattern).