javascript面向对象编程学习(三) —— 构造函数继承和组合继承

导读

javascript面向对象编程学习(一)
javascript面向对象编程学习(二) —— 原型链继承javascript

1、借用构造函数继承

一、 如何实现借用构造函数继承?

利用call()apply()方法,在子构造函数Child()中,调用Person.call(this, name),加强子构造函数实例;实质等同于复制父实例给子函数。java

1.1代码实现

function Person(name) {
     this.name = name;
     this.names = ['大魔王','魔鬼', '恶魔'];
     this.getName = function () {
         console.log(this.name)
     }
   }
  Person.prototype.say = function (){
     console.log('my name is ' + this.name);
   }
   
   function Child(name, age){
     // 继承Person
     Person.call(this, name);
     this.age = age;
   }
   
   var child = new Child('小魔王', 22);
   var child1  = new Child('大魔王', 25);
   console.log(child.names);   // ["大魔王", "魔鬼", "恶魔"]
   console.log(child1.names);  // ["大魔王", "魔鬼", "恶魔"]
   
   child.names.push('小魔王'); 
   
   console.log(child.names);   // ["大魔王", "魔鬼", "恶魔", "小魔王"]
   console.log(child1.names);  // ["大魔王", "魔鬼", "恶魔"]
   
   console.log(child.name);    // 小魔王
   console.log(child.age);     // 22
复制代码

二、为何能够用call()apply()方法来实现继承?

首先,咱们要了解一下call的定义:调用一个对象的一个方法,以另外一个对象替换当前对象。
也就是说,当执行Person.call(this, name)的时候,实质就是Personthis指向了Child
所以,实例child也有了Person的属性和方法了,也就实现了继承!编程

三、关系图以下:

借用构造函数继承

四、缺点:

  1. 只能继承父类的实例属性和方法,不能继承原型属性/方法;
    Personthis指向了Child, 也就是说,Child只是复制了Person的属性和方法,原型链并无和它产生关系;child实例的__proto__仍是指向Child。以下:
    构造函数继承2
  2. 没法实现构造函数的复用,每一个子类都有父类实例函数的副本,影响性能,代码会臃肿。

2、 组合继承

一、什么是组合继承?

原型链继承构造函数继承优势组合起来。使用构造函数继承实现对实例上的属性和和方法继承,使用原型链继承实现对原型上的属性和方法的继承。这样就能使在原型上定义的方法可以实现函数复用,而且没个实例也有本身的属性。app

二、代码实现

function Person(name) {
     this.name = name;
	 this.names = ['大魔王','魔鬼', '恶魔'];
   }
   
   Person.prototype.sayName = function (){
     console.log('my name is:' + this.name);
   }
   
   function Child(name, age){
     // 继承Person实例属性
     Person.call(this,name);
	 this.age = age;
   }
   
   // 继承原型的属性和方法
   Child.prototype = new Person();
   Child.prototype.constructor = Child; // 由于原型链继承,会把constructor指向改变,因此要从新指回自身
   Child.prototype.sayAge = function (){
     console.log('my age is:' + this.age);
   }
   
   
   const child = new Child('小魔王', 22);
   child.names.push('人');
   child.sayName();             // my name is:小魔王
   child.sayAge();              // my age is:22
   console.log(child.names);    // ["大魔王", "魔鬼", "恶魔", "人"]
   
   const child2 = new Child('人', 28);
   child2.sayName();            // my name is:人
   child2.sayAge();             // my age is:28
   console.log(child2.names);   // ["大魔王", "魔鬼", "恶魔"]
复制代码

三、关系图以下:

组合继承

四、缺点

父类实例的属性和方法既存在于子类的实例中也存在于原型中。以下图:函数

组合继承2

3、 总结

想要弄清楚构造函数继承,要先弄明白call()apply()方法的定义和使用,要清楚this指向。
组合继承,当你弄清楚原型链继承和构造函数继承,而后再把二者结合去思考,就天然而然懂了。
学习的最好的办法仍是实践;就譬如我这样动起手来,画图和敲代码等等,比只看而不去动手,要了解得更加透彻!
你的赞是对我最大的支持,也是我最大的动力!post

相关文章
相关标签/搜索