一个揭示原型模式能够扩展另一个揭示原型模式吗?

3

我想使用显式原型模式来扩展一个“类”。以动物和鱼为例。

我想要做到以下几点:

  • 让鱼继承自动物的原型
  • 在需要的情况下覆盖动物的成员
  • 向鱼的原型添加新成员
  • 在仍然使用两个“类”的显式原型模式的情况下实现以上所有操作

我可以创建Animal“类”:

var Animal = function(data) {
  this.name = ""
  this.color = "";
  this.weight = 0;
};


Animal.prototype = function() {
  var eat = function() {
    document.write(this.name + " is eating.<br>");
  }

  return {
    constructor: Animal,
    eat: eat
  };
}();

我可以创建一个继承自Animal的Fish“类”:

var Fish = function(data) {
  this.isSwimming = false;
};


Fish.prototype = new Animal();

鱼的原型是我遇到麻烦的地方。使用揭示原型模式是否可以对Fish进行操作,并仍然从Animal继承原型并在需要时覆盖Animal?(我不完全反对使用第三方库来完成此操作,但我宁愿不这样做。)例如,如何覆盖eat()并向Fish添加一个名为swim的新函数?
编辑:以下是我想出的解决方法。这似乎可以满足我的需求。我有什么遗漏吗?
Fish.prototype = new function(proto) {
  var base = proto.constructor;

  var eat = function(data) {
    new base().eat (data);//This is just to show you can call the base. If needed.
    document.write("fish eating.<br>");
  };

  var swim = function(){
    document.write("fish is swimming.<br>");
  };

  var thisProto = {
    constructor: Fish,
    eat: eat,
    swim: swim
  };

  for (var propt in thisProto) {
    proto[propt] = thisProto[propt];
  }

  return proto;
}(new Animal());

编辑:

在我接受的答案中,其中一个主要观点是不使用new关键字。因此,我研究了new关键字和Object.create()之间的区别。如果我理解正确,它们两者基本上做的事情是一样的,但Object.create()不会调用对象的构造函数,而new关键字会。如果你需要继承在构造函数中定义的某个东西,你需要使用new关键字或将该成员移动到原型中。

这是一个我用来进一步实验的Plunk: http://plnkr.co/edit/322WB4jyCJberABbb0P0


可能是如何在JS揭示原型模式中实现继承?的重复问题。 - Bergi
@Bergi,我正在测试您的答案。昨天我确实看到了另一个答案,但是就是无法理解它。现在我今天再看一下,它更有意义了,可能是重复的,但我认为您的答案添加了更多信息。 - Jeff
1个回答

2

我有什么遗漏吗?

有。

new function(proto) {

不要使用new

new base().eat (data);//This is just to show you can call the base. If needed.

不要使用new。你在这里创建了一个新实例,然而你想要的是从base.prototype获取eat方法并在你的Fish实例上调用它。

proto = new Animal()

不要使用 new


Fish.prototype = (function(super) {
  var proto = Object.create(super);

  function eat(data) {
    super.eat.call(this, data);
    document.write("fish eating.<br>");
  }
  function swim(){
    document.write("fish is swimming.<br>");
  }

  proto.constructor = Fish;
  proto.eat = eat;
  proto.swim = swim;

  return proto;
})(Animal.prototype);

我对这个级别的JavaScript开发很陌生,抱歉,但我对使用Object.create(super)创建动物对象的新实例如何初始化基础构造函数感到困惑,似乎存在一些不连贯的地方?这是否意味着proto指向与Animal.call传递参数相同的Animal实例?如果这是一个离题的问题,我很抱歉。 - user1790300
另外,为什么你调用了 super.eat.call(this, data); 而不是 proto.eat(data);? - user1790300
@user1790300 proto = Object.create(super) 不会创建动物实例(或像new Animal()一样初始化它),它只是创建一个从Animal.prototype继承的对象。该对象成为Fish.prototype,因此所有使用new Fish创建的实例都将从中继承。proto与构造函数或方法内部的this不同。 - Bergi
我该怎么做才能使用构造函数中初始化的实例,例如 var Fish = function(data) { Animal.call(this, data); };? - user1790300
@user1790300 你所说的“使用”是什么意思?只是 var fish = new Fish({}); fish.eat(); fish.swim(); 吗? - Bergi
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接