具有父类:
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
复制所有的原型方法和属性,一个接一个地从动物到狮子。
我不是javascript继承方面的专家。我通常使用MVC框架的前端开发,一切只是工作,但现在我也想了解如何继承原型的工作。
注意!我读了很多关于这个主题的文章,我知道有很多"插件"实现了Class的功能。这是不是我需要的。请回答问题,而不仅仅是链接有关主题的文章(除非这样回答了问题)。
谢谢!
有一个区别,复制两个原型之间的属性不会使它们彼此"连接",即:
$.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
的原型,就不会有这个,如下所示。
我最近写了一篇文章,解释了为什么原型继承很重要。虽然有点长,但值得一读。
直接回答你的问题,是的,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/
不,它们不一样。
Lion原型的第一个例子变成了一个Animal的实例。该实例确实继承了Animal原型,并将链接回该原型。如果动物原型被修改,实例将受到影响。
第二个例子是简单的从Animal原型中复制属性,而Lion 将不会链接到实际的Animal原型本身。正如其他人已经提到的,是的,这是有区别的。
在第一个示例中,对Animal原型的更改将改变Lion实例的行为。
在第二个例子中,Lion在调用$.extend()时继承了Animal 的功能。 第一种方法可能有一些有害的副作用,特别是: 动物的变化可以波及并打破狮子和它的后代。委托原型的这种动态更改属性通常被认为是一件好事,但是当它应用于多级继承时,它经常会导致问题。 第一种方法不允许选择性继承 from Animal。要么全有,要么全无。你想要香蕉,但你得到的是大猩猩、香蕉和整个丛林。(这个著名的问题被称为大猩猩/香蕉问题)。后一种方法允许您选择性地继承Animal: 构造函数根本不是必需的。你可以创建一个对象字面量animal,然后这样做: 更好的是,把它放在工厂函数中: 工厂函数比构造函数有很多优点,我在这里就不讨论了。你可以在我的回答中看到更多的细节:构造函数与工厂函数$.extend(Lion.prototype, { run: Animal.prototype.run, sleep: Animal.prototype.sleep });
instanceof
与连接断开-但instanceof
在任何情况下都不可靠。如果你重新分配动物原型,它就会崩溃。如果您试图跨执行上下文使用它,它就会中断。换句话说,无论选择哪种继承方法,都不要使用instanceof
。lion = Object.create(animal);
function lion(options) {
return $.extend(Object.create(lion), options);
}
这是纯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();