JS中几种继承方法


前言

提示:需要掌握如下知识点

  1. 原型链
  2. 箭头函数与普通函数的区别

一、原型链的继承

1. 代码

function Person() {
    this.name = "小明"
    this.eats = ["苹果"]

    // 此处使用普通函数,输出结果看下面的第一张图片
    this.getName = function () {
      console.log(this.name)
    }

    // 此处使用箭头函数,输出结果看下面的第二张图片
    /*this.getName = () => {
      console.log(this.name)
    }*/
  }

  Person.prototype.get = function () {
    console.log("Person.prototype 上的方法!")
  }

  function Student() {
  }

  Student.prototype = new Person()

  let stu1 = new Student()
  stu1.name = "小花"
  stu1.eats.push("香蕉")

  console.log(stu1.name); // 输出:小花
  console.log(stu1.eats); // 输出:['苹果','香蕉']
  stu1.getName()  // 输出:小花
  stu1.get()  // 输出:Person.prototype 上的方法!

  console.log("--------------")

  let stu2 = new Student()

  console.log(stu2.name); // 输出:小明
  console.log(stu2.eats); // 输出:['苹果','香蕉']
  stu2.getName()  // 输出:小明
  stu2.get()  // 输出:Person.prototype 上的方法!

2. 输出结果

图1:
在这里插入图片描述
图2:
在这里插入图片描述

3. 优缺点

优点: 父类方法可以复用

缺点:

  1. 父类所有的引用类型数据(对象,数组)会被子类共享,更改一个子类的数据,其他数据会受到影响,一直变化
  2. 子类实例不能给父类构造函数传参

二、构造函数的继承

1. 代码

function Person() {
    this.name = "小明"
    this.eats = ["苹果"]

    // 此处使用普通函数,输出结果看下面的第一张图片
    this.getName = function () {
      console.log(this.name)
    }

    // 此处使用箭头函数,输出结果看下面的第二张图片
    /*this.getName = () => {
      console.log(this.name)
    }*/
  }

  Person.prototype.get = function () {
    console.log("Person.prototype 上的方法!")
  }

  function Student() {
  	Person.call(this)
  }

  

  let stu1 = new Student()
  stu1.name = "小花"
  stu1.eats.push("香蕉")

  console.log(stu1.name); // 输出:小花
  console.log(stu1.eats); // 输出:['苹果','香蕉']
  stu1.getName()  // 输出:小花
  // stu1.get()  // 

  console.log("--------------")

  let stu2 = new Student()

  console.log(stu2.name); // 输出:小明
  console.log(stu2.eats); // 输出:['苹果']
  stu2.getName()  // 输出:小明
  // stu2.get()  // 输出:Person.prototype 上的方法!

2. 输出结果

在这里插入图片描述

3. 优缺点

优点: 父类的引用类型的数据不会被子类共享,不会互相影响

缺点: 子类不能访问父类原型属性上的方法和参数

三、组合继承

1. 代码

function Person() {
    this.name = "小明"
    this.eats = ["苹果"]

    // 此处使用普通函数,输出结果看下面的第一张图片
    this.getName = function () {
      console.log(this.name)
    }

    // 此处使用箭头函数,输出结果看下面的第二张图片
    /*this.getName = () => {
      console.log(this.name)
    }*/
  }

  Person.prototype.get = function () {
    console.log("Person.prototype 上的方法!")
  }

  function Student() {
	 Person.call(this)
  }

  Student.prototype = new Person()

  let stu1 = new Student()
  stu1.name = "小花"
  stu1.eats.push("香蕉")

  console.log(stu1.name); // 输出:小花
  console.log(stu1.eats); // 输出:['苹果','香蕉']
  stu1.getName()  // 输出:小花
  stu1.get()  // 输出:Person.prototype 上的方法!

  console.log("--------------")

  let stu2 = new Student()

  console.log(stu2.name); // 输出:小明
  console.log(stu2.eats); // 输出:['苹果']
  stu2.getName()  // 输出:小明
  stu2.get()  // 输出:Person.prototype 上的方法!

2. 输出结果

在这里插入图片描述

3. 优缺点

优点:

  1. 父类可以复用
  2. 父类构造函数中的引用属性数据不会被共享

缺点: 会调用两次父类的构造函数,会有两份一样的属性和方法,会影响性能

四、寄生组合继承

1. 代码

function Person() {
    this.name = "小明"
    this.eats = ["苹果"]

    // 此处使用普通函数,输出结果看下面的第一张图片
    this.getName = function () {
      console.log(this.name)
    }

    // 此处使用箭头函数,输出结果看下面的第二张图片
    /*this.getName = () => {
      console.log(this.name)
    }*/
  }

  Person.prototype.get = function () {
    console.log("Person.prototype 上的方法!")
  }

  function Student() {
	 Person.call(this)
  }

  const Fn = function(){
  }
  Fn.prototype = Person.prototype
  Student.prototype = new Fn()

  let stu1 = new Student()
  stu1.name = "小花"
  stu1.eats.push("香蕉")

  console.log(stu1.name); // 输出:小花
  console.log(stu1.eats); // 输出:['苹果','香蕉']
  stu1.getName()  // 输出:小花
  stu1.get()  // 输出:Person.prototype 上的方法!

  console.log("--------------")

  let stu2 = new Student()

  console.log(stu2.name); // 输出:小明
  console.log(stu2.eats); // 输出:['苹果']
  stu2.getName()  // 输出:小明
  stu2.get()  // 输出:Person.prototype 上的方法!
  
  console.log(stu2)
	

2. 输出结果

在这里插入图片描述

3. 优缺点

目前最优的一个继承方案

五、ES6的 class类继承(extends)

1. 代码

class Person {
    constructor() {
      this.name = "小明"
      this.eats = ["苹果"]
      this.getName = function () {
        console.log(this.name)
      }
    }
    get = function () {
      console.log("Person.prototype 上的方法!")
    }
  }
  class Student extends Person{

  }
  let stu1 = new Student()
  stu1.name = "小花"
  stu1.eats.push("香蕉")

  console.log(stu1.name); // 输出:小花
  console.log(stu1.eats); // 输出:['苹果','香蕉']
  stu1.getName()  // 输出:小花
  stu1.get()  // 输出:Person.prototype 上的方法!

  console.log("--------------")

  let stu2 = new Student()

  console.log(stu2.name); // 输出:小明
  console.log(stu2.eats); // 输出:['苹果']
  stu2.getName()  // 输出:小明
  stu2.get()  // 输出:Person.prototype 上的方法!

  console.log(stu2)

2. 输出结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小超爱编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值