6

我有 Java 背景,最近一直在尝试 JavaScript 继承。我开始编写一些对象,在阅读了一些示例后,我发现了最适合我的代码风格。

这是我所拥有的:

var Class = function() {};
Class.extend = function(p_constructor) {
    var Superclass = this;
    // the following line confuses me
    p_constructor.prototype = Object.create(Superclass.prototype);
    p_constructor.prototype.constructor = p_constructor;
    p_constructor.extend = Superclass.extend;
    return p_constructor;
};

所以现在当我想定义一个扩展类的对象时,我只需输入:

var Person = Class.extend(function(p_firstName, p_lastName) {
    this.firstName = p_firstName;
    this.lastName = p_lastName;
});

以下将是正确的:

var p = new Person('john', 'smith');
p instanceof Person; // true
p instanceof Class; // true

我只是很难理解Class.extend函数中以下几行之间的有效区别是什么:

/* 1) */ p_constructor.prototype = new Superclass();
/* 2) */ p_constructor.prototype = Superclass.prototype;
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype);
/* 4) */ p_constructor.prototype = Object.create(Superclass);

我确实意识到如果某些超级构造函数抛出错误,使用第一行并不是很明智,但是第 2、3 和 4 行之间到底有什么区别?

4

1 回答 1

7

回答我自己的问题:

/* 1) */ p_constructor.prototype = new Superclass();

就像我说的,使用它不是很明智,因为它实际上创建了整个 Superclass 对象。原型继承的重点是共享原型对象,因此可以避免冗余函数(有时是对象)定义。

/* 2) */ p_constructor.prototype = Superclass.prototype;

如果您可以确定构造函数的原型永远不会被第三方修改,那就可以了。假设使用你的类的人想要向它的原型添加额外的功能。更改 p_constructor 的原型将直接影响超类的原型,并可能在超类的行为中引入错误。所以使用下一行代码:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype);

这将创建一个新对象(实例),其原型(实际上是__proto__变量)设置为超类的原型。现在的任何更改p_constructor.prototype都不会更改超类的行为。

/* 4) */ p_constructor.prototype = Object.create(Superclass);

上面一行有效,但没有意义,因为它只将原型设置为超类的构造函数。

此外,以下行也让我感到困惑:

p_constructor.prototype.constructor = p_constructor;

它对 p_constructor 的行为没有影响,它只是使对构造函数的引用在实例化对象中可用。一个巧妙的技巧是将超类也添加到原型中:

p_constructor.prototype.superclass = Superclass;

然后以下代码将起作用:

function Constructor(p_params) {
    // call constructor of the superclass
    this.superclass(p_params);
}
于 2013-12-02T22:12:08.537 回答