函数中的继承

一. 继承【知道】

1.1 什么是继承

  • 生活中的继承
    子承父业
  • 程序中的继承
    子类型继承父类型的成员 (把多个子类型的共同成员提取到父类型中)
    • 学生
    • 老师

1.2 对象的“继承”

  • 概念:继承是类型和类型之间的关系,对象的“继承”本质是对象的拷贝,把一个对象的所有成员拷贝给另一个对象。

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // 第一个对象
    var obj1 = {name:'张三', age:18};
    // 第二个对象
    var obj2 = {
    name:'李四',
    age:17,
    sex:'男',
    sayHi:function () {
    console.log('大家好,我叫' + this.name)
    }
    }
    // 把一个对象中的属性和方法,拷贝到另一个对象中
    function extend (parent,child) {
    for (var key in parent) {
    if (child[key] === undefined) {
    child[key] = parent[key];
    }
    }
    }
    // 拷贝之前的obj1
    console.log(obj1); // {name: "张三", age: 18}
    // 把obj2中的属性或方法拷贝到obj1中
    extend(obj2,obj1);
    // 拷贝之后的obj1
    console.log(obj1); // {name: "张三", age: 18, sex: "男", sayHi: ƒ}


1.3 原型继承

  • 继承:类型和类型之间的关系

  • 案例:学生类型、老师类型 继承 Person类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    // 人构造函数
    function Person () {
    this.name = '名字';
    this.age = 18;
    }
    Person.prototype.sayHi = function() {
    alert('大家好,我叫' + this.name);
    };

    // 学生构造函数
    function Student (stuId) {
    this.stuId = stuId;
    }
    // 老师构造函数
    function Teacher (money) {
    this.money = money;
    }

    // 通过学生的原型让学生继承人
    Student.prototype = new Person();
    Student.prototype.constructor = Student;
    // 通过老师的原型让老师继承人
    Teacher.prototype = new Person();
    Teacher.prototype.constructor = Teacher;
    // 创建学生对象
    var stu1 = new Student(10010);
    console.log(stu1);
    // 创建老师对象
    var t1 = new Teacher(100);
    console.log(t1);
  • 图解

注意:当设置了构造函数的prototype之后,别忘记设置constructor

问题:原型继承,无法设置构造函数的参数Student.prototype = new Person();只执行一次,无法给属性传值,可以方便的继承父类型的原型中的方法,但是属性的继承无意义

1.4 借用构造函数

  • call方法
    ​ 使用call可以改变函数中的this,并且可以立即调用函数
    ​ 和bind不同的是,bind会返回一个新函数,而call是直接调用

    • 语法:函数名或方法名.call(obj [,params]);

      • obj:函数名或方法名对应的函数体中的this的指向。
      • params, 函数名或方法名调用时需要传入的参数(一个或多个),可选。
    • 代码:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      // 规则:this 的指向是在代码执行时决定的。
      function fn (age) {
      this.age = age;
      console.log(this);
      }
      // 直接调用函数
      fn(50); // 当直接调用时,函数中的this执向window。 window.fn(50),window可以省略;
      // 创建要给对象
      var obj = {};
      // 通过call让obj去借用window的fn,并立即执行
      fn.call(obj,100); // 函数中this指向obj
  • 借用构造函数实现继承

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    // 人构造函数
    function Person (name,age) {
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayHi = function() {
    alert('大家好,我叫' + this.name);
    };

    // 学生构造函数
    function Student (name,age,stuId) {
    // 借用Person
    Person.call(this,name,age);
    this.stuId = stuId;
    }
    // 老师构造函数
    function Teacher (name,age,money) {
    // 借用Person
    Person.call(this,name,age);
    this.money = money;
    }

    // 创建学生对象
    var stu1 = new Student('张三',17,'10086');
    console.log(stu1);
    // 创建老师对象
    var t1 = new Teacher('孔子',18,10000000);
    console.log(t1);

借用构造函数继承的问题:无法继承方法

1.5 组合继承

  • 什么是组合继承?
    ​ 就是让原型继承 和 借用继承一起使用。

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    // 人构造函数
    function Person (name,age) {
    this.name = name;
    this.age = age;
    }
    Person.prototype.sayHi = function() {
    alert('大家好,我叫' + this.name);
    };

    // 学生构造函数
    function Student (name,age,stuId) {
    // 借用Person
    Person.call(this,name,age);
    this.stuId = stuId;
    }
    // 继承人原型中的方法
    Student.prototype = Person.prototype;
    // 老师构造函数
    function Teacher (name,age,money) {
    // 借用Person
    Person.call(this,name,age);
    this.money = money;
    }
    // 继承人原型中的方法
    Teacher.prototype = Person.prototype;

    // 创建学生对象
    var stu1 = new Student('张三',17,'10086');
    console.log(stu1);
    // 创建老师对象
    var t1 = new Teacher('孔子',18,10000000);
    console.log(t1);
  • 新的问题

    • 问题:若给学生的原型上增加一个考试方法exam,老师类型也会出现exam方法。

    • 代码:

      1
      2
      3
      4
      5
      Student.prototype.exam = function () {
      alert('学生考试');
      };
      console.log(stu1);
      console.log(t1);
    • 图示结果:

  • 解决问题代码:

    • 原因:Student的引用 和 Teacher的引用 指向同一个对象。

    • 解决方式:为两个类型单独拷贝

    • 代码:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      // 把一个对象中的属性和方法,拷贝到另一个对象中
      function extend (parent,child) {
      for (var key in parent) {
      if (child[key] === undefined) {
      child[key] = parent[key];
      }
      }
      }
      // 人构造函数
      function Person (name,age) {
      this.name = name;
      this.age = age;
      }
      Person.prototype.sayHi = function() {
      alert('大家好,我叫' + this.name);
      };
      // 学生构造函数
      function Student (name,age,stuId) {
      // 借用Person
      Person.call(this,name,age);
      this.stuId = stuId;
      }
      // 拷贝人原型中的方法
      extend(Person.prototype, Student.prototype);
      // 老师构造函数
      function Teacher (name,age,money) {
      // 借用Person
      Person.call(this,name,age);
      this.money = money;
      }
      // 拷贝人原型中的方法
      extend(Person.prototype, Teacher.prototype);
      // 创建学生对象
      var stu1 = new Student('张三',17,'10086');
      // 创建老师对象
      var t1 = new Teacher('孔子',18,10000000);
      // 给学生原型单独加上一个方法
      Student.prototype.exam = function () {
      alert('学生考试');
      };
      console.log(stu1);
      console.log(t1);
    • 图示结果:

文章目录
  1. 1. 一. 继承【知道】
    1. 1.1. 1.1 什么是继承
    2. 1.2. 1.2 对象的“继承”
    3. 1.3. 1.3 原型继承
    4. 1.4. 1.4 借用构造函数
    5. 1.5. 1.5 组合继承
|