【问题标题】:JavaScript - Dynamic Prototype Pattern + Parasitic Combination InheritanceJavaScript - 动态原型模式 + 寄生组合继承
【发布时间】:2016-10-22 09:26:12
【问题描述】:

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

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 中对此进行了测试,它似乎工作正常,我只是想确保没有任何我遗漏的东西会在以后使用此模式/继承时导致问题。

另外,我知道这本书有点老了,有没有新的对象创建和继承标准?

【问题讨论】:

  • inheritPrototype 需要使用Object.create 而不是Object
  • 我不得不说“动态原型模式”在我眼里看起来很丑……原型方法也应该是静态的,而不是动态的,所以有人可能会争辩说在构造函数中创建它们(即使只是动态的) ) 是一种不好的做法。如果您寻找语法封装,请在构造函数+继承+原型周围使用 IIFE,或者只使用 ES6 类。

标签: javascript oop inheritance design-patterns


【解决方案1】:

这两种方法似乎都失效

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

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

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);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-28
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多