如何在JavaScript中创建无法实例化的抽象基类

Ale*_*yan 31 javascript inheritance design-patterns

我上课了

function Node() {
    //implementation
}
Run Code Online (Sandbox Code Playgroud)

和另一堂课

function AttributionalNode() {
    this.prototype.setAttr = function (attr) {
        this.atText = attr;
    };
}

AttributionalNode.prototype = new Node();
AttributionalNode.prototype.constructor = AttributionalNode;
Run Code Online (Sandbox Code Playgroud)

如何使类Node()无法实例化?比如我试试的时候

var node = new Node();
Run Code Online (Sandbox Code Playgroud)

所以它引发了一个例外?

All*_*ock 47

在支持ECMAScript 2015(又名ES6)类语法的JavaScript引擎中,这可以使用new.target元属性来完成:

function Node() {
   if (new.target === Node) throw TypeError("new of abstract class Node");
}
Run Code Online (Sandbox Code Playgroud)

或使用类语法:

class Node {
   constructor () {
      if (new.target === Node) throw TypeError("new of abstract class Node");
   }
}
Run Code Online (Sandbox Code Playgroud)

在任何一种情况下,只需定义AttributionalNode为:

class AttributionalNode extends Node {
   constructor () {
      super();
   }
   setAttr(attr) {
      this.atText = attr;
   }
}

new Node();               // will throw TypeError
new AttributionalNode();  // works fine
Run Code Online (Sandbox Code Playgroud)

有关更详细的说明,new.target请参阅本文档的第4.2节.

  • 你能为`new.target`提供参考吗? (2认同)
  • `new.target` 和 `this.constructor` 有什么区别吗? (2认同)

lev*_*evi 13

这可行:

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();
Run Code Online (Sandbox Code Playgroud)

注意:您不能引用this.prototype构造函数内部,因为原型只是构造函数的属性,而不是实例的属性.

另外,请参阅此处以获取有关如何正确扩展JS类的好文章.

  • @AlexandrSargsyan没有.我更新了示例来演示这一点. (2认同)

Cir*_*sta 7

根据@ levi的答案,您可以使用类似的解决方案来使用ES6(现在new.target还没有建立):

你可以看到它在Babel的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();
Run Code Online (Sandbox Code Playgroud)