2015-05-31 17 views
25

Tôi có một lớpLàm thế nào để tạo lớp cơ sở trừu tượng trong JavaScript mà không thể được khởi tạo

function Node() { 
    //implementation 
} 

và lớp khác

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

AttributionalNode.prototype = new Node(); 
AttributionalNode.prototype.constructor = AttributionalNode; 

Làm thế nào để làm cho lớp Node() để nó có thể không được khởi tạo? ví dụ: khi tôi thử

var node = new Node(); 

Vì vậy, nó có ngoại lệ?

+0

Đặt 'ném ngoại lệ mới()' vào hàm tạo, có thể? Tôi không biết nếu đó là hợp lệ trong Javascript. –

+0

Nói chung, không nên đặt các thuộc tính nguyên mẫu trong hàm hàm tạo. – Pointy

Trả lời

10

này sẽ làm việc:

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();

Lưu ý: bạn không thể tham khảo this.prototype bên trong constructor, như nguyên mẫu chỉ là một tài sản của hàm constructor, không phải của các trường hợp.

Ngoài ra, see here để có bài viết hay về cách mở rộng các lớp JS đúng cách.

+0

Nó thông qua lỗi khi một số lớp cố gắng kế thừa từ Node() –

+2

@AlexandrSargsyan Nó không. Tôi đã cập nhật ví dụ để minh họa điều này. – levi

41

Trong động cơ JavaScript hỗ trợ ECMAScript 2015 (aka ES6) cú pháp lớp, điều này có thể được thực hiện bằng cách sử dụng new.target meta-tài sản:

function Node() { 
    if (new.target === Node) throw TypeError("new of abstract class Node"); 
} 

hoặc sử dụng cú pháp lớp:

class Node { 
    constructor() { 
     if (new.target === Node) throw TypeError("new of abstract class Node"); 
    } 
} 

trong cả hai trường hợp, chỉ cần xác định AttributionalNode là:

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

new Node();    // will throw TypeError 
new AttributionalNode(); // works fine 

Để được giải thích chi tiết hơn về new.target, xem phần 4.2 của this document.

+1

Bạn có thể cung cấp tham chiếu cho 'new.target' không? –

+0

new.target không hoạt động! –

+1

Nếu bạn muốn biết liệu nó có hỗ trợ hay không: https://kangax.github.io/compat-table/es6/#new.target. Tại thời điểm này, không có hỗ trợ, như đã nêu. –

5

Thích ứng @ câu trả lời levi, bạn có thể đi với một giải pháp tương tự cho việc sử dụng với ES6 ngày hôm nay (như new.target không được thành lập chưa):

Bạn có thể nhìn thấy nó chạy trên repl Babel của: 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(); 
Các vấn đề liên quan