js之三种继承方式

千峰逆战班,千峰斯坦僧接班人之一打卡第二天其二。

我要成为这次疫情期间,最闲得码农!!!!

一、为什么要有JS继承

假如每一个实例对象,都要有自己的属性和方法的副本。这不仅无法做到数据共享,也是极大的资源浪费。(这就和我们现实中会继承父母的资产一样,你是可以选择不继承的,但是浪费钱啊)

二、JS继承的三种方式

1.原型继承

	//构建一个父类
    function Person(name) {
       this.name = name
     }
     //父类原型对象上添加一个函数sayHi
     Person.prototype.sayHi = function () {
       console.log('hello world')
    }
    // 实例化对象p,并传入参数的属性name值为Jack
    var p = new Person(‘Jack’)
    console.log(p)
    /*
     p = {
        name: 'Jack',
        __proto__: Person.prototype {
          sayHi: function () {},
          __proto__: Object.prototype
        }
      }
    */

  // 构建一个子类
   function Student(age) {
     this.age = age
   }
  // 让 子类 继承 父类
   Student.prototype = new Person('Jack')
   
   var s1 = new Student(18)
   console.log(s1)
   /*
   	s1 = {
        age: 18,
        __proto__: Student.prototype === p {
          name: 'Jack',
          __proto__: Person.prototype {
            sayHi: function () {},
            __proto__: Object.prototype
          }
        }
      }
   */

原型链继承总结:子类.prototype = 父类的实例;
//原型链继承是改变了子类的原型指向(这就像我和爸爸之间的关系,我的原型链(proto)指向了我的爸爸,你要问我有什么,我把我所有的属性和方法展示给你看,然后我的身上还有一个 proto ,从那里可以查询到我爸爸有啥)

缺点:

  • 继承下来的属性并没有在该子类身上,而是在其 proto
  • 要用的属性和方法虽然被继承,但是在多个位置,不便于寻找
  • (不便于寻找)对书写,维护和阅读代码不太友好

2.构造函数继承
//前提:需要使用call函数改变函数内部 this 指向的方法

 // 1. 一个父类
    function Person(name, gender) {
      this.name = name
      this.gender = gender
    }
    Person.prototype.sayHi = function () {
      console.log('hello world')
    }
    // 2. 一个子类
    function Student(age, name, gender) {
      this.age = age

      // 这里的 this 指向 的是 Student 的当前实例(s1)
      // 调用 Person 函数, 把函数内部的 this 指向了 Student 的实例
      //   也就是现在让 Person 函数内部的 this 指向了 s1
      // Person 里面的代码
      //   this.name 相当于是 s1.name
      // 利用父类构造函数体, 向子类身上添加成员
     Person.call(this, name, gender)
    }

    var s1 = new Student(18, 'Rose', '男')
    console.log(s1)

构造函数继承总结:父类.call(this,属性,方法)
//构造函数继承方式是利用父类构造函数体, 向子类身上添加成员(我爸会钓鱼,我不会,所以我要继承他的钓鱼方法就要让他教我【爸爸.call(我,钓鱼)】)

优点:

  • 不用一个个在 proto 上找属性和方法了
  • 要用几个属性,在call函数里传参就行(你想学几个技能,就让你爸教给你几个)
    缺点:
  • 只能继承父类的属性和方法,不能继承父类原型的属性和方法(因为你只找到你爸爸教你技能,所以你爷爷会啥你不清楚)
  • 父类的方法被继承,每new对象时都会有同样的函数空间出现,所以继承父类方法会造成资源浪费
    //因为构造函数继承支持多重继承,所以你要继承哪个父类,就 哪个父类.call(this,属性)(这意思就是你要向谁学习技能,就让他.call(你,技能))

3.组合继承
//组合继承:把原型链继承和构造函数继承融合在一起。

 // 1. 父类构造函数
    function Person(name, age) {
      this.name = name
      this.age = age
    }
    Person.prototype.sayHi = function () {
      console.log('hello world')
    }

    // 2. 子类构造函数
    function Student(gender, name, age) {
      this.gender = gender
      
      // 构造函数继承
      //   call 方法的参数
      //   第一个是要改变的this 指向
      //   从第二个参数开始依次给函数传递参数
      Person.call(this, name, age) // 这里的 this 就是 Student 的实例
      // 调用一个 Person 函数, 并且把 Person 里面的 this 改变成 Student 的实例
    }

    // 原型继承
    //   能继承属性和方法的
    //   s1 的 sayHi 方法是依靠这个 原型继承 继承下来的
    Student.prototype = new Person()
    
    var s1 = new Student('男', 'Jack', 18)
    console.log(s1)

组合继承总结:父类.call(this,属性,属性),再子类.prototype = 父类的实例
优点:

扫描二维码关注公众号,回复: 9433497 查看本文章
  • 将属性继承下来了,不用再一个个到_proto_找了(构建函数继承的优点)
  • 方法也继承下来了(原型链继承的优点)
    注意:组合继承方式的子类里面调用继承方式不能调换,因为构建函数是根据参数决定继承哪些属性或方法,如果不写,等同于不继承
    好好学习,天天向上。中国加油,武汉加油,千峰加油!
发布了3 篇原创文章 · 获赞 8 · 访问量 1153

猜你喜欢

转载自blog.csdn.net/weixin_44395929/article/details/104523669
今日推荐