JS 继承 通俗易懂

 JS继承

  • 1.JS是面向过程,不是面向对象【面向对象有工厂模式、混合模式......】,js继承是面向对象的一大特征;
  • 2.那么面向对象跟面向过程有什么区别呢?

面向过程:

    优点:性能比面向对象高,因为类调用时需要实例化,开销比较大,比较消耗资源;比如单片机、嵌入式开发、 Linux/Unix等一般采用面向过程开发,性能是最重要的因素。
    缺点:没有面向对象易维护、易复用、易扩展
 

面向对象:好处之一就是显著的改善了软件系统的可维护性。

    优点:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统 更加灵活、更加易于维护 
    缺点:性能比面向过程低

  • 3.js继承有三大特征:封装、继承、多态
  •               分别简述一下这三大特征:
  •      ①封装:由于js中是没有类的概念的,我们需要通过new操作符来构建实例,用函数将业务包裹起来;
  •      ②多态:传参的多少或者不传参会呈现出不同的形态
  •      ③继承:继承有两大类一类是es5继承,一类是es6继承;

JS 继承 通俗易懂

 

  • 一、es5继承: 有五种,常用的有三种

  • 1. 原型链继承: 把父类的实例赋值给子类的原型;(父类的实例作为子类的原型)
  • 声明父类 People  【首字母大写】
  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        
    </body>
    </html>
    <script>
       //声明父类
       function People(){
           this.name="小明",
           this.sleep=function(){
               console.log(this.name+'会睡觉');
           }
       }
    
       //每个函数都有一个prototype属性,别成为显示原型
       //将eat方法挂载到原型上
       People.prototype.eat=function(){
           console.log(this.name+'会吃');
       }
    
    
       //声明子类
       function Women(){
            this.age=18
       }
    
    
       //子类继承父类
       //把父类的实例赋值给子类原型,就叫做原型链继承
    
       Women.prototype=new People();
    
       let one=new Women()
       console.log(one.name);
       one.sleep()
       one.eat()
       console.log(one.age)    //这个年龄也会打印出来  ---> 18
    
    </script>

 上图就是原型链继承,看一下打印的结果

JS 继承 通俗易懂

     优点:易于实现,父类新增实例与属性子类都能访问

     缺点:无法实现多继承,不能向父类传参

  •  2.借用构造函数继承: 复制父类实例属性给子类
<script>
   //声明父类
   function People(){
       this.name="小明",
       this.sleep=function(){
           console.log(this.name+'会睡觉');
       }
   }

   //声明子类  //可以传参
   function Women(){
       //通过call方法改变this指向
        People.call(this)    //将父类People中的this.name && this.sleep拿到了Women子类中
   }

   let one=new Women() 
   console.log(one.name);
   one.sleep()
  

</script>

 根据上图,最终打印的已过

 JS 继承 通俗易懂

      优点:可以向父类传参

      缺点:无法继承父类原型上的方法

  •  3.组合式继承:结合原型链构造函数继承

调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用

 function People(name, age) {
        this.name = name
        this.age = age 
    }
    People.prototype.eat = function () {
        console.log(this.name + this.age + 'eat sleep')
    }

    function Woman(name, age) {
        People.call(this, name, age)
    }
    Woman.prototype = new People();
    console.log(one.constructor===People)  --> 为true

    //当修改了this指针
    Woman.prototype.constructor = Woman;  //修改this指针,将子类原型上的constructor修改为子类实例
    console.log(one.constructor===People)  --> 为false

    let wonmanObj = new Woman("ren", 27);
    wonmanObj.eat(); 

      优点:

  • 函数可以复用

  • 不存在引用属性问题

  • 可以继承属性和方法,并且可以继承原型的属性和方法

      缺点:由于调用了两次父类,所以产生了两份实例

 4.原型继承  

     用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。

    特点:类似于复制一个对象,用函数来包装。

    缺点:1、所有实例都会继承原型上的属性。

                          2、无法实现复用。

  • 5.寄生组合式继承 (原型式继承外面套了个壳子)

       特点:没有创建自定义 

  • 二、es6继承

  • es6继承⽤class定义类,⽤extends继承类,⽤super()表示⽗类

  • class People{
      constructor(name='wang',age='27'){  //可以设置默认值
        this.name = name;
        this.age = age;
      }
    //在constructor外面就是定义的原型上的方法
      eat(){
        console.log(`${this.name} ${this.age} eat food`)
      }
    }
    
    

    声明子类

  • //继承父类
    class Woman extends People{ 
       constructor(name = 'ren',age = '27'){ 
         //继承父类属性
         super(name, age); 
       } 
        eat(){ 
         //继承父类方法
          super.eat() 
        } 
    } 
    let wonmanObj=new Woman('xiaoxiami'); 
    wonmanObj.eat();
    
  •   class son extends father{ }

    子类可以没有自己的构造方法,没有可以调用父亲的,但是有构造方法先调用父亲

 

 

上一篇:Elasticsearch6.6.x 版本的学习(一)es 安装 和 JestClient 进行操作Elasticsearch6.6.x


下一篇:2021-09-30