JavaScript函数的继承---原型链、借用构造函数、组合继承

JavaScript函数的继承

什么是继承?通俗来讲就是子承父业。web

对象之间的继承(对象拷贝)
  • for …in … 的做用以及语法
// for ... in .语句能够遍历对象属性
for(var key in 对象){
  // key 每次遍历的属性名
}

获取属性值的方法:
【1】对象. 属性名
【2】对象[属性名]
能够经过遍历对象的成员,将这些属性添加给另外一个对象。从而实现继承,这不是真正的继承,只是在拷贝对象的成员。svg

<script>
   var fatherObj = {
     name: 'father',
     gender: 'male',
     cars: ['劳斯莱斯','阿尔法','阿斯顿马丁'],
     houses: ['独栋别墅', '古堡'],
     play: function(){
       console.log('高尔夫')
     }
   }
  //  使用for.. in ..遍历对象中的属性
  // 复制父级对象的成员给继承对象(子)
   var sonObj = {
     name: 'son'
   }
   for(var key in fatherObj){
    // 不给sonObj复制同名的属性
    if(sonObj[key]){
      continue;
    }
    sonObj[key]=fatherObj[key]
   }
   console.dir(sonObj)
  </script>

在这里插入图片描述

继承实现
  1. 原型链继承
    由于原型链的存在,对象访问一个属性或方法时,会在自身找,找不到会到原型对象中找,因此咱们能够借助原型对象来实现继承
<script>
    // 父类
    function Person(){
      this.name = 'zss',
      this.gender = 'male',
      this.age = '22'
    }
    // 子类
    function Student(){
      this.score = 100
    }
    // 改变子类原型对象
    Student.prototype = new Person()
    Student.prototype.constructor = Student
    // 此时Studentd的实例s1,经过改变原型对象,继承了Person的属性
    var s1 = new Student()
    console.log(s1.constructor)
    console.dir(s1)
  </script>
  • 此时,s1就继承了Person的属性。

在这里插入图片描述

  1. 借用构造函数实现继承
    使用call()方法调用其余构造函数,并将其this变成当前对象。从而实现,当前对象继承其余构造函数的属性。
<script>
    // 父类
    function Father(name, gender, age) {
      this.name = name,
        this.gender = gender,
        this.age = age,
        console.log(this) // 指向window 
    }
    Father()
    // 子类
    function Son(name, gender, age, score) {
      // 此时,Son的this指向实例化的 s1对象
      // 使用 call()方法,改变this指向
      Father.call(this, name, gender, age) // 到这,就把 Father的 this 指向了 s1对象
      this.score = score
    }
    var s1 = new Son('zwt', 'male', '18', 100)
    console.dir(s1)
  </script>

在这里插入图片描述

  1. 组合继承
    组合继承(combination inheritance),有时候也叫作伪经典继承,指的是将原型链和借用构造函数的技术组合到一块,从而发挥两者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而经过借用构造函数来实现对实例属性的继承。这样,既经过在原型上定义方法实现了函数复用,又可以保证每一个实例都有它本身的属性。
<script>
    // 父类型
    function Teacher(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
    }
    // 将 Person 类中需共享的方法放到 prototype 中,实现复用
    Teacher.prototype.sayHi = function () {
      console.log('你们好,我是' + this.name);
    }
    //子类型
    function Student(name, age, sex, score) {
      //借用构造函数
      Teacher.call(this, name, age, sex);
      this.score = score;
    }
    // 改变Student的原型对象为Person的原型对象
    // Student.prototype = Teacher.prototype; // 这样写有问题,Exam方法是 Student独有的,这样写致使 p1 也会有Exam方法
    Student.prototype = new Teacher() // 此时 Student.prototype 中的 constructor 被重写了,会致使 s1.constructor === Teacher
    Student.prototype.constructor = Student; //将 Student 原型对象的 constructor 指针从新指向 Student 自己
    // 学生特有
    Student.prototype.Exam = function () {
      console.log('你们好,我是学生,我是要考试的');
    }
    //此时s1就继承J Person的属性和方法
    var s1 = new Student('zs', 18, '男', 100);
    console.dir(s1);
    var p1 = new Teacher('zs2', 28, '男')
    console.dir(p1)
    // console.log(s1.constructor === Teacher)
  </script>

在这里插入图片描述
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优势,成为了JavaScript中最经常使用的继承模式。并且,instanceof 和isPrototypeOf()也可以用于识别基于组合继承建立的对象。函数