How to create Abstract base class in JavaScript that can't be Instantiated
In JavaScript engines that support ECMAScript 2015 (aka ES6) class syntax, this can be accomplished using the new.target
meta-property:
function Node() {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
or using class syntax:
class Node {
constructor () {
if (new.target === Node) throw TypeError("new of abstract class Node");
}
}
in either case, just define AttributionalNode
as:
class AttributionalNode extends Node {
constructor () {
super();
}
setAttr(attr) {
this.atText = attr;
}
}
new Node(); // will throw TypeError
new AttributionalNode(); // works fine
For a more detailed explanation of new.target
see section 4.2 of this document.
This would work:
function Node() {
if (this.constructor === Node) {
throw new Error("Cannot instantiate this class");
}
}
function AttributionalNode() {
Node.call(this); // call super
}
AttributionalNode.prototype = Object.create(Node.prototype);
AttributionalNode.prototype.setAttr = function (attr) {
this.atText = attr;
};
AttributionalNode.prototype.constructor = AttributionalNode;
var attrNode = new AttributionalNode();
console.log(attrNode);
new Node();
Note: you cannot refer to this.prototype
inside the constructor, as the prototype is only a property of the constructor function, not of the instances.
Also, see here for a good article on how to properly extend JS classes.
Adapting @levi's answer, you can go with a similar solution for using with ES6 today (as new.target
isn't established yet):
You can see it running on Babel's repl: http://bit.ly/1cxYGOP
class Node {
constructor () {
if (this.constructor === Node)
throw new Error("Cannot instantiate Base Class");
}
callMeBaby () {
console.log("Hello Baby!");
}
}
class AttributionalNode extends Node {
constructor () {
super();
console.log("AttributionalNode instantiated!");
}
}
let attrNode = new AttributionalNode();
attrNode.callMeBaby();
let node = new Node();