写点什么

继承(二)

作者:Jason199
  • 2022 年 7 月 11 日
  • 本文字数:3619 字

    阅读完需:约 12 分钟

继承(二)

 借用构造函数继承

借用继承 / call 继承

        通过改变 父类 构造函数的 this 指向来达到继承效果

        核心代码 在字类构造函数体内, 父类.call(字类的实例)

构造函数的执行

        1. 是一个普通函数, 可以当作函数直接调用

        2. 当作普通函数执行的时候, this 指向谁, 就向谁身上添加内容

        3. call 方法可以改变函数的 this 指向

借用继承的优缺点

        优点:

          1. 继承来的属性是在自己身上

          2. 我们一个实例化过程在一个位置传递参数

        缺点:

          1. 只能继承父类构造函数体内的内容

          2. 父类原型上的内容不能继承

function Student(gender, name, age) {      this.gender = gender      // Person('Jack', 18)      // 使用 call 方法改变一下 Person 函数内部的 this 指向      // 改变成指向谁, Person 就会向谁的身上添加一个 name 一个 age      // Person.call('Jack', 18)      // 这个位置的 this 指向 Student 的实例, 因为 new Student      // Person 函数内部的 this 指向 Student 的实例 this === s      Person.call(this, name, age)      // 这个函数执行完毕以后, 会像 Student 的实例身上添加一个 name 一个 age    }
Student.prototype.study = function () { console.log('study') } const s = new Student('男', 'Jack', 18) console.log(s)
复制代码

  组合继承

把 原型继承 和 借用构造函数继承 合并在一起使用

组合继承的优缺点

        优点:

          1. 父类构造函数体内和原型上的内容都能继承

          2. 继承下来的属性放在自己身上

          3. 在一个位置传递所有参数

        缺点:

          1. 当你给字类添加方法的时候, 实际上是添加在了父类的实例身上

function Student(gender, name, age) {      this.gender = gender// 借用继承, 目的: 把属性继承在自己身上      Person.call(this, name, age)    }// 原型继承, 目的: 继承父类原型上的方法    Student.prototype = new Person()// 书写属于 Student 自己的方法    Student.prototype.study = function () { console.log('study') }// 使用 Student 创建实例    const s = new Student('男', 'Jack', 18)    console.log(s)
复制代码

拷贝继承

拷贝继承(for in 继承)

利用 for in 循环的特点, 来继承所有的内容

        先实例化一个父类的实例

        使用 for in 循环来遍历这个实例对象

          因为 for in 循环不光遍历对象自己, 还会遍历 __proto__

        直接把父类实例身上的所有内容直接复制到字类的 prototype

        核心代码

          const p = new Person('Jack', 18)

          for (var key in p) {

            console.log(key)

          }

拷贝继承的优缺点

        优点:

          1. 父类的构造函数体内的和原型上的都可以继承

          2. constructor 能正常配套

          3. 添加自己的方法的时候, 确实是在自己的原型身上

        缺点:

          1. for in 循环: for in 循环需要一直遍历到 Object.prototype

          2. 不能继承 不可枚举 的属性

          3. 继承来的属性不再自己身上

function Student(gender, name, age) {      this.gender = gender// for in 继承      const p = new Person(name, age)      for (let key in p) {        Student.prototype[key] = p[key]      }    }    Student.prototype.study = function () { console.log('study') }    const s = new Student('男', 'Jason', 18)    console.log(s)
复制代码

寄生继承

        是一种伪继承

        1. 构造函数不要写 return

          return 基本数据类型, 写了白写

          return 复杂数据类型, 构造函数没有意义

        核心代码

          const instance = new Person(name, age)

           return instance

function Student(name, age) {     this.gender=  '男'
// 寄生继承 const instance = new Person(name, age) return instance }// s 确实是 new Student 来的// s 就是 Student 的实例, 但是真实的内容是 Person 的实例 const s = new Student('Jason', 18) Student.prototype.study = function () {} console.log(s)
复制代码

寄生继承 2

        出现了第二种寄生继承

        不直接寄生实例, 寄生原型

寄生继承的优缺点

        优点: (号称完美继承)

          1. 原型和构造函数体内的都能继承下来

          2. 寄生原型的话, 自己的属性和方法依旧可以添加和使用

        缺点:

          1. 寄生实例的时候, 没有自己的任何内容

          2. 寄生原型的时候, 一旦修改原型上, 父类的实例也会有这些方法

// 寄生继承2    function Student(gender) {      this.gender = gender    }// 寄生原型    Student.prototype = Person.prototype // 该自己的    Student.prototype.stduy = function () {}    const s = new Student('男')    console.log(s)
复制代码

 寄生式组合继承(完美继承)

        合并了 寄生继承 + 原型继承 + 独立第三方构造函数 + 借用继承

        核心代码

       

  (function () {        function Abc(name, age) {}        // 让 第三方构造函数 来寄生 父类 的原型          Abc.prototype = Person.prototype            Student.prototype = new Abc()  })();
复制代码


  function Person(name, age) {      this.name = name      this.age = age    }    Person.prototype.sayHi = function () { console.log('hello world') }    function Student(gender, name, age) {      this.gender = gender // 借用继承: 继承来了父类的属性      Person.call(this, name, age)    }    (function () {      function Abc(name, age) {}// 让 第三方构造函数 来寄生 父类 的原型      Abc.prototype = Person.prototype      const a = new Abc()      Student.prototype = a    })()// 当你去修改 Student 的 prototype 的时候// 相当于在修改 Abc 的实例, 和 Person 父类没有任何关系   Student.prototype.study = function () { console.log('study') }   const s = new Student('男', 'Jason', 18)    console.log(s)//从现在开始就是如下展示     // a = {      //  name: 'Jack',     //   age: 18,     //  __proto__: Person.prototype {     //   sayHi: function () {},     //     __proto__: Object.prototype     //   }     // }
复制代码

另外 s 的属性

 此时: Student.prototype = {          name: 'Jason',          age: 18,          __proto__: Person.prototype {            sayHi: function () {},            __proto__: Object.prototype          }        }      将来实例化 s 的时候        s = {          gender: '男',          __proto__: { // 第三方构造函数的实例            name: 'Jason',            age: 18,            __proto__: Person.prototype {              sayHi: function () {},              __proto__: Object.prototype            }          }        }
复制代码

ES6 类的继承

        ES6 把继承这个使用变成了 关键字

          1. extends

            class 字类类名 extends 父类 {}

          2. super()

            constructor 里面书写一个 super()

            super(name, age) 等价于 Person.call(this, name, age)

        注意:

          1. super 需要写在 constructor 里面

          2. 如果你要写自己的属性, 必须写在 super 后面

          3. ES6 的继承可以继承 ES5 的构造函数也可以继承 ES6 的类

function Person(name, age) {      this.name = name      this.age = age    }    Person.prototype.sayHi = function () { console.log('hello world') }class Student extends Person {      constructor (gender, name, age) {        super(name, age)        this.gender = gender      }      study () {        console.log('study')      }    }    const s = new Student('男', 'Jack', 18)    console.log(s)    class Abc extends Student {      constructor () {        super('女', 'Rose', 20)      }    }   const a = new Abc()    console.log(a)
复制代码

继承到这里就写完了 ,后面我们开始 jQuery.晚安

发布于: 刚刚阅读数: 4
用户头像

Jason199

关注

还未添加个人签名 2022.04.29 加入

一条努力上岸的咸鱼

评论

发布
暂无评论
继承(二)_js_Jason199_InfoQ写作社区