我一直试图了解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');
这种方法给我留下了相当多的冗余,因为我不能将特定于实例的属性委托给基类(在原型分配时,属性值是未知的)。因此每个子类必须重复该属性。 有没有推荐的解决方法?
奖金问题:是否有合理的方法可以避免“新”操作符,或者是否会被视为违反该语言的新手?
答案 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”的文章,它向您展示了如何定义自定义属性,静态方法,静态属性等。