拥有父类:
function Animal() {
// do something
}
Animal.prototype.walk = function() {
alert('I am walking.');
};
和孩子类:
function Lion() {
// do something
}
如果我希望Lion
继承Animal
的原型,通常的做法是:
Lion.prototype = new Animal();
// Set the constructor to Lion, because now it points to Animal
Lion.prototype.constructor = Lion;
这与此有什么不同(结果不是性能)?
$.extend(Lion.prototype, Animal.prototype);
对于非jquery开发人员:$.extend
将所有原型方法和属性一个一个地从Animal复制到Lion。
我不是javascript中继承的大专家。我通常使用MVC框架进行前端开发,其中一切正常,但现在我也想了解继承原型是如何工作的。
注意! 我阅读了很多关于这个主题的文章,我知道有很多"plugins"实现了 Class 功能。这是不我需要的东西。请回答这个问题,而不只是链接有关该主题的文章(除非有答案)。
谢谢!
答案 0 :(得分:3)
有一点不同,在两个原型之间复制属性并不会使它们彼此“连接”,即:
$.extend(Lion.prototype, Animal.prototype);
// add one more method to the prototype
Animal.prototype.test = function() {
alert('test');
};
var x = new Lion();
x.test(); // TypeError: Object <Lion> has no method 'test'
如果您使用new Animal()
作为Lion
的原型,那么您就不会这样做,如here所示。
答案 1 :(得分:3)
我最近写了一篇解释Why Prototypal Inheritance Matters的文章。这有点长,但值得一读。
要直接回答您的问题,是Lion.prototype = new Animal
与$.extend(Lion.prototype, Animal.prototype)
不同,因为:
我联系你的帖子解释了真正的原型继承(即使用原型模式的原型继承)。
如果您在JavaScript中使用了真正的原型继承,那么这就是您的程序的样子:
var animal = {
create: function () {
return this.extend();
},
walk: function () {
alert("I am walking.");
}
};
var lion = animal.extend({
create: function () {
return animal.create.call(this);
}
});
此处extend
函数是我链接到您的帖子中的函数。
将此与您使用构造函数模式进行原型继承的代码进行对比。
这是一个小提琴,展示了真正的原型继承:http://jsfiddle.net/6x4BU/
答案 2 :(得分:1)
不,他们不一样。
Lion原型的第一个例子成为Animal的实例。该实例继承自Animal原型并将链接回该原型。 如果动态原型被修改,实例将受到影响。
第二个例子只是从Animal原型中复制属性,而Lion 将不会链接到实际的Animal原型本身。
答案 3 :(得分:0)
正如其他人已经提到的那样,是的,存在差异。
在第一个示例中,对Animal原型的更改将更改Lion实例的行为。
在第二个示例中,Lion在$ .extend()调用时继承了Animal 的功能。
第一种方式有一些可能有害的副作用,特别是:
对动物的改变会涟漪并打破狮子及其后代。委托原型的动态更改属性通常被认为是一件好事,但当它应用于多级继承时,它经常会导致问题。
第一种方法不允许来自Animal的选择性继承。这是全有或全无。你想要香蕉,但你得到的是大猩猩,香蕉和整个丛林。 (这个着名的问题叫做大猩猩/香蕉问题)。后一种方法允许您选择性地继承Animal:$.extend(Lion.prototype, { run: Animal.prototype.run, sleep: Animal.prototype.sleep });
instanceof
打破连接 - 但instanceof
在任何情况下都不可靠。如果你重新分配动物原型,它将会破裂。如果您尝试在执行上下文中使用它,它会中断。换句话说,不使用instanceof
,无论您选择哪种继承方法。
根本不需要构造函数。您可以创建一个名为animal的对象文字并执行此操作:
lion = Object.create(animal);
更好的是,把它放在工厂功能中:
function lion(options) {
return $.extend(Object.create(lion), options);
}
工厂函数比构造函数有很多优点,我不会在这里讨论。您可以在此帖子的回答中查看更多详细信息:Constructor function vs Factory functions
答案 4 :(得分:0)
这是纯JavaScript中的基本原型继承
// base class declaration
function Animal (arg) {
this.arg = arg;
}
// just a method in the Animal class, it can be whatever you want
Animal.prototype.roar = function () {
alert(this.arg);
};
// object that inherits the base class
function Lion (arg) {
// the call to the super constructor
Animal.call(this, arg);
}
// the prototypical inheritance
Lion.prototype = Object.create(Animal.prototype);
// the constructor needs to be set so that it does not show as the base constructor
// otherwise the constructor for all instances of Lion will show as Animal
Lion.prototype.constructor = Lion;
var symba = new Lion('the lion is roaring');
symba.roar();