什么是原型继承的真实例子?

时间:2014-01-26 16:10:59

标签: javascript prototypal-inheritance

我正在尝试升级JavaScript(我在工作中没有使用它),并且很好地围绕了构造函数以及如何实例化从它们继承属性的新对象。

但通常要真正学到一些东西,我需要在我正在研究的真实项目中使用它,并在行动中看到它。

问题是,我正在阅读的所有内容都使用这些示例来解释继承:

function Apple (type) {
    this.type = type;
    this.color = "red";
    this.getInfo = getAppleInfo;
}

function Car( model, year, miles ) {

  this.model = model;
  this.year = year;
  this.miles = miles;

  this.toString = function () {
    return this.model + " has done " + this.miles + " miles";
  };
}

function makeBaby(parent, name) {

  var baby = Object.create(parent);

  baby.name = name;

  return baby;
}

正如您可能想象的那样,这些例子(水果,汽车和父母)对于学习概念的目的肯定是有帮助的,但实际上并没有将它们付诸实践。

有没有人举例说明原型继承如何在生产级Web应用程序中起作用?

2 个答案:

答案 0 :(得分:6)

这不仅仅是原型继承,但用例也适用于经典继承。

通常,您希望将一个类的属性和功能扩展到另一个类。一个很好的例子是视图类。它有一个draw方法可以绘制到屏幕上。重用代码的好方法。

因此,您不必手动将一个类的所有属性复制到另一个类,而只需从基类扩展,您将拥有它的所有功能,以及添加自己的实现。

使用继承的示例代码:

/**
 * View1
 */
function View1 {
  this.viewId = 'view-1';
  this.template = '<some html here>'
}

View1.prototype.draw = function () {
  var ourView = document.getElementById(this.viewId);

  // ps. I know this is redundant, but it's here for illustration purposes.
  var newElement = document.createElement('div');
  ourView.appendChild(newElement);

  ourView.innerHTML = this.template;
}


/**
 * View2
 */
function View2 {
  this.viewId = 'view-2';
  this.template = '<some html here>'
}

View2.prototype.draw = function () {
  var ourView = document.getElementById(this.id);

  // ps. I know this is redundant, but it's here for illustration purposes.
  var newElement = document.createElement('div');
  ourView.appendChild(newElement);

  ourView.innerHTML = this.template;
}

如您所见,有很多重复的代码。

将其与使用继承的代码进行比较:

/**
 * View1
 */
function View1 {
  this.viewId = 'view-1';
  this.template = '<some html here>'
}

View1.prototype.draw = function () {
  var ourView = document.getElementById(this.viewId);

  // ps. I know this is redundant, but it's here for illustration purposes.
  var newElement = document.createElement('div');
  ourView.appendChild(newElement);

  ourView.innerHTML = this.template;
};

/**
 * View2
 */
function View2 {
  this.viewId = 'view-2';
  this.template = '<some html here>'
}

Object.assign(View2.prototype, View1.prototype);

View2永远不需要从View1重新实现代码。相反,它只是重复使用它。

答案 1 :(得分:3)

原型继承在任何您希望使用面向对象的方法和继承来模拟问题的任何地方都很有用。

一个很好的例子是Backbone.js如何提供基类,如Model,Collection和View。在您的应用程序中,您可以扩展这些基类以执行特定的操作,例如

var ProfileSummary = Backbone.View.extend({
  render: function () {
    this.$el.html("Profile summary view");
  }
});

现在,ProfileSummary是一个具有(继承)所有Backbone.View方法和功能的类,但您可以调整render函数的功能。

请注意,extend方法是Backbone为您提供使用原型继承扩展这些类的简单方法的方法 - 请参阅代码以获取更多详细信息https://github.com/jashkenas/backbone/blob/e6f8f7ea69370b0891cc969a2c68ebb78ad6e49b/backbone.js#L1551-L1588

如果这有助于您的应用程序,您可以在类层次结构中创建多个图层。例如。

var MyBaseView = Backbone.View.extend({
  //common functionality in all views within yur app
});

var ProfileSummary = MyBaseView.extend({
   //functionality specific to the profile summary view
});

var ProfileSummaryEditor = ProfileSummary.extend({
  //makes the profile summary editable
});

希望这会有所帮助。如果我误解了你的问题,请告诉我。