js的手写继承,起底这些名字的含义?

446 阅读3分钟

寄生组合式继承

const SuperClass = function () {}
const SubClass = function () {  
    SuperClass.apply(this);
}
Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype);

原型式继承

const obj = {};
const subObj = Object.create(obj);

说明:

  • 所谓原型式继承,就是以某个对象为原型,获得一个新的对象。
  • Object.create(obj) 相当返回新对象{},并将其__proto__笨蛋属性,设置为obj
  • 这是js最标准的继承行为,也是js的威力所在。java其实只能算是面向类的语言,而js才是真正面向对象的语言!因为js本身是不存在类的概念的,能够描述行为的只有对象。java的继承,会复制父类的所有方法给子类。但原型式继承,并没有复制的开销,subObj仅仅是委托了父对象
  • 其实原型式继承,倒是有点像通常说的“继承vs组合”中组合的理念,组合的代码是低入侵且灵活的。

寄生式继承

function inheritObj(obj, name) {  
    const subObj = Object.create(obj);  
    subObj.name = name;  
    return subObj;
}

说明:

  • 有些书说,就是对原型式继承的二次封装,如上所示

  • 但是。。。黑人问号脸???我感觉这是不对的。因为这毫无意义,这和原型式继承有什么区别呢?多了个成员变量name?可是搜出来几乎有的文章都是这样解释的

  • 然后,我搜到了提出寄生式继承的大佬Douglas的一篇博客文章Classical Inheritance in JavaScript (crockford.com) 其中这样描述Parasitic Inheritance

Instead of inheriting from Parenizor, we write a constructor that calls the Parenizor constructor

  • 因此,正确的寄生式继承应当是这样的,咳咳,我看了后心中暗自窃喜

    function inheritObj(obj, name) {
    const subObj = new SubClass();
    subObj.name = name;
    }

  • 这才是所谓的寄生继承,因为父类的实例,就像一只寄生兽一样,静静地封装在子类实例中~

  • 可是我又看了下红宝书,看看是怎么解释寄生式继承的,然后,我发现红宝书就是用原型继承的二次封装的例子,晕,原来前面的例子是对的,属实我多想了。但是书又说了,寄生式继承实际上是对一个基准对象进行增强并返回,甚至原型式继承也不是必须的。简单来说,你写个inheritObject方法,传入基准对象obj,返回一个新的对象,那就可以认为是寄生式继承,因为这相当于你完全不在意类型和构造函数,管他呢,抓到老鼠的就是好猫猫

  • 其实上面Douglas的那片文章,就是在吐糟传统的继承在js中并不见得多好,太过笨重了,因此寄生式继承的概念,是他十分提倡的,简单好用,何乐不为

最后,寄生组合式继承

  • 那就是 寄生+组合
  • 组合就是 构造函数继承 + 原型链继承
  • 所以 寄生组合式 = 寄生继承 + 构造函数继承 + 原型链继承,你学废了吗?

好吧,再来看看寄生组合式的代码

const SubClass = function () {    
    SuperClass.apply(this);  
}  
Object.setPrototypeOf(SubClass.prototype, SuperClass.prototype);
  • SuperClass.apply(this); 就是构造函数继承

  • 修改了SubClass.prototype 就是原型链继承

  • 而以SuperClass.prototype为基准对象增强SubClass.prototype,就是寄生式继承的思想

  • 所以 1 + 1 + 1 = 3 咯,你学废了吗?

  • 最后的最后,Object.setPrototypeOf 可以不产生垃圾对象,也许性能能好那么一点点吧,相比SubClass.prototype = Object.create(SuperClass.prototype)的赋值写法

  • 最后的最后的最后,其实这样写并没有什么性能的提升,只不过,在写下这行代码的顷刻间,追求完美代码的心灵被满足了一下,好似正道的光,照在前方。我好像悟了