继承原型



具有父:

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),因为:

  1. 在第一种情况下,你使用委托。
  2. 在第二种情况下,你使用串联。

我链接给你的文章解释了真正的原型继承(即使用原型模式的原型继承)。

如果你在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: $.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);
}

工厂函数比构造函数有很多优点,我在这里就不讨论了。你可以在我的回答中看到更多的细节:构造函数与工厂函数

这是纯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();

最新更新