Private methods for JS classes
Published
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).