【JS手撕面试题】寄生组合式继承

258 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

寄生组合式继承

要求

补全JavaScript代码,要求通过寄生组合式继承使"Chinese"构造函数继承于"Human"构造函数。要求如下:

  1. 给"Human"构造函数的原型上添加"getName"函数,该函数返回调用该函数对象的"name"属性
  2. 给"Chinese"构造函数的原型上添加"getAge"函数,该函数返回调用该函数对象的"age"属性

思路

寄生组合式继承是引用类型最理想的继承范式,它融合了组合式继承与寄生式继承的优点,而组合式继承又是融合了原型链借用构造函数的技术,从而发挥两者之长,所以寄生组合式继承实际是三种技术的融合。

  • 寄生式继承的思路是:创建一个仅用于封装继承过程的函数
  • 组合式继承的思路是:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

这一题的思路是:

  1. 先创建一个inheritPrototype函数,该函数属于寄生式继承模式,作用是实现实现对原型属性和方法的继承:
// subType子类构造函数,superType父类构造函数
function inheritPrototype(subType,superType){
	 // Object.create() 方法用于创建一个新对象,使用现有的对象来作为新创建对象的原型(prototype)。
     var prototype = Object.create(superType.prototype); // 创建父类型的一个副本对象
     prototype.constructor = subType; // 修复prototype的constructor 
     subType.prototype = prototype; // 将prototype设为subType的原型
 }

这里涉及到原型链的知识:一个构造函数的prototype指向它的原型对象,而它的原型对象的constructor属性又指向到这个构造函数。上面的代码中因为要让prototype设置为subType的原型,所以prototype.constructor需要指向到subType。

调用inheritPrototype后,subType就继承了superType的属性和方法,这些属性和方法存在于subType的原型上,这样一来subType的所有实例就能访问到同一个存在的属性或方法(这些属性和方法相当于是公有的)。

  1. 给"Human"构造函数的原型上添加"getName"函数:

Human.prototype.getName=function (){
   return this.name;
}


  1. 通过借用构造函数来实现ChineseHuman实例属性的继承:
function Chinese(name,age) {
	// 继承了Human,还传了参数
    Human.call(this,name); // 借用构造函数模式
    this.age = age;
    this.color = 'yellow';
}

Chinese内部调用Human构造函数,实际上是为Chinese的实例设置了Human上具有的属性和方法(不包含Human原型上的属性和方法),这样一来Chinese的所有实例就能拥有自己的属性和方法(这些属性和方法相当于是私有的)。

  1. 调用inheritPrototype(Chinese,Human); 来实现ChineseHuman原型属性和方法的继承。
  2. 给"Chinese"构造函数的原型上添加"getAge"函数:
Chinese.prototype.getAge=function(){
    return this.age;
}

代码

    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}


function Human(name) {
    this.name = name
    this.kingdom = 'animal'
    this.color = ['yellow', 'white', 'brown', 'black']
}

Human.prototype.getName = function () {
    return this.name;
}

function Chinese(name,age) {
    Human.call(this,name);
    this.age = age;
    this.color = 'yellow';
}

inheritPrototype(Chinese,Human);


Chinese.prototype.getAge = function() {
    return this.age;
}