继承基构造函数属性的传统方式如下:
function Cat(name, owner) {
Animal.call(this, name); // call the base constructor
this.owner = owner;
}
Cat.prototype = new Animal;
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
alert(this.name + " jumping");
};
上面的代码等价于其他语言的下面的类:
class Cat extends Animal {
constructor(name, owner) {
super(name);
this.owner = owner;
}
jump() {
alert(this.name + " jumping");
}
}
继承属性的新方法是完全一样的,只是我们new Animal
用Object.create(Animal.prototype)
. 我们更喜欢新方式的原因是:
- 调用
new Animal
是不必要的开销。构造Cat
函数无论如何都会再次调用它。
- 调用
new Animal
可能不会返回空白对象。它可能会为对象添加一些属性。
- 我们还不知道
new Animal
用什么参数来调用。因此,调用它是没有意义的。
因此,现在首选的继承方式是:
function Cat(name, owner) {
Animal.call(this, name); // call the base constructor
this.owner = owner;
}
Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.constructor = Cat;
Cat.prototype.jump = function () {
alert(this.name + " jumping");
};
请注意,调用基本构造函数很重要,因为它可能会进行一些初始化,这是实例正常工作所必需的。
如果您对以经典风格编写 JavaScript 代码感兴趣,请查看以下描述原型类同构的答案。以下代码取自上述答案:
function CLASS(prototype, base) {
switch (typeof base) {
case "function": base = base.prototype;
case "object": prototype = Object.create(base, descriptorOf(prototype));
}
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
function descriptorOf(object) {
return Object.keys(object).reduce(function (descriptor, key) {
descriptor[key] = Object.getOwnPropertyDescriptor(object, key);
return descriptor;
}, {});
}
使用该CLASS
函数,我们可以在 JavaScript 中定义伪类,如下所示:
var Animal = CLASS({
constructor: function (name) {
this.name = name;
},
getName: function () {
return this.name;
}
});
var Cat = CLASS({
constructor: function (name, owner) {
Animal.call(this, name);
this.owner = owner;
},
jump: function () {
alert(this.name + " jumping");
}
}, Animal);
还有其他方法可以在 JavaScript 中进行继承。我建议你阅读我关于原型继承为何重要的博文,以了解更多关于 JavaScript 中的继承的信息。