JavaScript多级继承

时间:2010-02-06 12:57:43

标签: javascript inheritance

我一直试图了解JavaScript继承。 令人困惑的是,似乎有许多不同的方法 - 克罗克福德提出了相当多的方法,但不能完全理解他的散文(或者可能只是没有把它与我的特定情况联系起来)。

以下是我到目前为止的一个例子:

// base class
var Item = function( type, name ) {
    this.type = type;
    this.name = name; // unused
};

// actual class (one of many related alternatives)
var Book = function( title, author ) {
    this.name = title; // redundant (base class)
    this.author = author;
};
Book.prototype = new Item('book'); // duplication of "book"

// instances
var book = new Book('Hello World', 'A. Noob');

这种方法给我留下了相当多的冗余,因为我不能将特定于实例的属性委托给基类(在原型分配时,属性值是未知的)。因此每个子类必须重复该属性。 有没有推荐的解决方法?

奖金问题:是否有合理的方法可以避免“新”操作符,或者是否会被视为违反该语言的新手?

4 个答案:

答案 0 :(得分:3)

  

是否有合理的方法来避免使用“新”操作符

您真正想要做的是创建一个在其原型链中具有Item.prototype的JavaScript对象。但是你不想调用Item构造函数,因为这没有意义:你没有实例化Item,你只是在做一个子类。

您必须以某种方式使用new来获取该原型链,但您不必使用Item来获取原型。您可以使用相同的原型创建一个新的非构造函数,但不执行任何操作,基类可以在实际上不想实例化对象时调用它们:

function Item(type) {
    this.type= type;
};

function Book(title, author) {
    Item.call(this, 'book');
    this.name= title;
    this.author = author;
};
function Item_nonconstructor() {}
Item_nonconstructor.prototype= Item.prototype;
Book.prototype= new Item_nonconstructor();

您可以通过多种方式将其视为不那么难看,例如:

Function.prototype.subclass= function(base) {
    var c= Function.prototype.subclass.nonconstructor;
    c.prototype= base.prototype;
    this.prototype= new c();
};
Function.prototype.subclass.nonconstructor= function() {};

function Book(title, author) {
    Item.call(this, 'book');
    this.name= title;
    this.author = author;
};
Book.subclass(Item);

或者,您可以考虑将构造函数移动到初始化函数或其他各种方法。 JavaScript中没有单一的可接受的类/实例系统。有关JavaScript对象模型的详细讨论,请参阅this question

答案 1 :(得分:3)

我会告诉你我是如何做到这一点的: -

 function Item(type, name)
 {
    if (arguments.length > 0)
    {
        this.type = type;
        this.name = name;
    }
 }

 function Book(title, author)
 {
   Item.call(this, "book", title);
   this.author = author;
 }
 Book.prototype = new Item();

所以我在这里做了几件事,当我检测到一个新实例被创建为原型时,我跳过基类中的一些初始化代码。

避免重复的真正启动器是使用Item.call作为基类构造函数。这样可以避免原始文件中的重复。

至于避免new如果你说出你想要的原因会有帮助吗?然而,一种简单的方法是直接向“类函数”添加函数,而不是函数的原型: -

Book.Create = function (title, author) { return new Book(title, author); }


var aBook = Book.Create("Code Complete 2", "Steve McConnell");

虽然我在这里看到的收益微乎其微。

答案 2 :(得分:0)

我从来都不喜欢基本原型方法,John Resig(jQuery的最大作者)有一种替代方法,我发现OO背景更简单,更容易,更自然: {{3 }} 即可。根据你的评论(我有同样的想法),我真的建议看看。

如果您不喜欢自己所处的风格,并且听起来您 对此感到满意......请尽早更改。有一些不同的选择,很少曾经一种方式在javascript中做某事。

答案 3 :(得分:0)

以下是使用更深层继承模型的另一种方法:

//The functions we are going to use 
function A() {}
function B() {}
function C() {}
function D() {}
function E() {}

//set up the inheritance chain (order is important!)
D.prototype = new E();
C.prototype = new D();
B.prototype = new C();
A.prototype = new B();

//Add custom functions to each
A.prototype.foo = function() {
    console.log("a");
};
B.prototype.bar = function() {
    console.log("b");
};
C.prototype.baz = function() {
    console.log("c");
};
D.prototype.wee = function() {
    console.log("d");
};
E.prototype.woo = function() {
    console.log("e");
};

//Some tests
a = new A();
a.foo();
a.bar();
a.baz();
a.wee();
a.woo();

这可以为您提供所需的大部分内容。我在我的博客上写了一篇关于“nested inheritance in javascript”的文章,它向您展示了如何定义自定义属性,静态方法,静态属性等。