JavaScript - 动态原型模式+寄生组合继承

时间:2016-10-22 09:26:12

标签: javascript oop inheritance design-patterns

我正在为Web开发人员使用专业JavaScript,并且有关于对象创建和继承的问题。在本书中,动态原型模式被讨论为一种很好的组合构造函数/原型模式,同时保持构造函数和原型封装到Object定义。像这样:

function Person(name, age, job) {
  this.name = name;
  this.age = age;
  this.job = job;

  if (typeof this.sayName != "function") {
    Person.prototype.sayName = function () {
      return this.name;
    };
  }
}

在书中讨论的所有对象创建模式中,我觉得这个模型看起来最好。然后在讨论继承时,书中说寄生组合继承被认为是最优的继承范式。如下:

function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}

SuperType.prototype.sayName = function() {
  return this.name;
};

function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;
}

inheritPrototype(SubType, SuperType);

SubType.prototype.sayAge = function() {
  return this.age;
}

如您所见,此代码使用组合构造函数/原型模式来创建对象,其中原型在原始对象创建之外声明。我的问题是,将动态原型模式与寄生组合继承相结合是否有任何问题,如下所示:

function inheritPrototype(subType, superType){
  var prototype = Object.create(superType.prototype);
  prototype.constructor = subType;
  subType.prototype = prototype;
}

function SuperType(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];

  if (typeof this.sayName != "function") {
    SuperType.prototype.sayName = function() {
        return this.name;
    };
  }
}

function SubType(name, age) {
  SuperType.call(this, name);
  this.age = age;

  if (typeof this.sayAge != "function") {
    SubType.prototype.sayAge = function() {
        return this.age;
    };
  }
}

inheritPrototype(SubType, SuperType);

我已经在jsfiddle here中对此进行了测试,它似乎工作正常,我只是想确保我没有丢失的东西,以后会导致问题这种模式/继承。

另外,正如我所知,这本书有点旧,是否有对象创建和继承的新标准?

1 个答案:

答案 0 :(得分:0)

这两种方法似乎已损坏

即使构造函数尚未被调用,也应该可以使用给定的对象原型属性。另一方面,似乎这打破了单一责任原则,因为构造函数负责定义原型,而它应该初始化正在构造的对象

只有一个问题:如何构建基础对象之前如何继承给定对象的原型?

var B = Object.create(A.prototype);

等待!除非某些代码之前调用A.prototype,否则new A()不会包含预期的属性。

// Ugly as hell!
new A();
var B = Object.create(A.prototype);

总之,不要尝试快捷方式JavaScript:学习它更好,不要尝试用无用/无意义函数包装继承。

实际上,ECMA-Script 6及以上标准已经定义了语法糖,使JavaScript原型链看起来像经典继承:

class B extends A 
{
}

......这绝对等同于:

function B() {}
B.prototype = Object.create(A.prototype);